C# 从巨大的 url 列表中下载数据

标签 c# parallel-processing webclient parallel.foreach downloadstring

<分区>

我有一个巨大的显示状态的网页列表,我需要检查这些状态。 一些网址位于同一站点内,另一组位于另一个站点上。

现在我正在尝试通过使用如下代码以并行方式执行此操作,但我感觉我造成了过多的开销。

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());
}

关于C# 从巨大的 url 列表中下载数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19389938/

相关文章:

C# 将 T 转换为 long

c# - 服务中的 BackgroundWorker 组件

parallel-processing - 为什么计算数字奇偶校验的代码可以并行运行**?

c++ - arduino 网络客户端随机卡住

c# - 如何为WebClient()设置暂停功能?

c# - 在 Unity 中创建浮力船

c# - 在单个异步方法中进行多次等待是否有任何目的

c - C有模板吗?

c++ - 'unbounded_buffer' 中的消息数

c# - 如何使用 WebClient DownloadStringAsync 来避免卡住 UI?