我有一个巨大的显示状态的网页列表,我需要检查这些状态。
一些网址位于同一站点内,另一组位于另一个站点上。
现在我正在尝试通过使用如下代码以并行方式执行此操作,但我感觉我造成了过多的开销。
while(ListOfUrls.Count > 0){
Parallel.ForEach(ListOfUrls, url =>
{
WebClient webClient = new WebClient();
webClient.DownloadString(url);
... run my checks here..
});
ListOfUrls = GetNewUrls.....
}
这能否以更少的开销完成,并更多地控制我使用/重用的网络客户端和连接数量?那么,那到底能不能更快的完成工作呢?
Parallel.ForEach
适用于受 CPU 限制的计算任务,但在您的情况下,它会为同步 IO 限制调用(例如 DownloadString
)不必要的 block 池线程。您可以通过使用 DownloadStringTaskAsync
和任务来提高代码的可伸缩性并减少它可能使用的线程数:
// non-blocking async method
async Task<string> ProcessUrlAsync(string url)
{
using (var webClient = new WebClient())
{
string data = await webClient.DownloadStringTaskAsync(new Uri(url));
// run checks here..
return data;
}
}
// ...
if (ListOfUrls.Count > 0) {
var tasks = new List<Task>();
foreach (var url in ListOfUrls)
{
tasks.Add(ProcessUrlAsync(url));
}
Task.WaitAll(tasks.ToArray()); // blocking wait
// could use await here and make this method async:
// await Task.WhenAll(tasks.ToArray());
}