Parallel.ForEach中的WebClient.DownloadFile()

时间:2011-03-29 00:43:45

标签: c# webclient parallel-processing

此代码可以正常工作:

Parallel.ForEach(photos, item =>
            {
                WebClient webClient = new WebClient();
                webClient.DownloadFile(item.src_big, "C:\\pic" + item.ID + ".jpg");
            });

此代码抛出“WebClient请求期间发生异常”。 :

foreach (Photo p in photos)
        {
            Task.Factory.StartNew(() =>
                {
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile(p.src_big, "C:\\pic" + p.ID + ".jpg");
                });
        }

我有两个问题:

1)在第一个代码中,我使用多个WebClient对象进行下载。第二个代码也是如此,为什么我会得到异常呢?

2)我正在尝试这两个版本来确定下载照片的最快方式,在我的案例中来自facebook。我想知道是否有另一种方法更快,也许WebRequest.Create()?

2 个答案:

答案 0 :(得分:7)

在第二种情况下你是closing over the loop variable - 试试这个:

foreach (Photo p in photos)
        {
            Photo photo = p;
            Task.Factory.StartNew(() =>
                {
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile(photo.src_big, "C:\\pic" + photo.ID + ".jpg");
                });
        }

此外Parallel.ForEach()是同步的 - 执行完毕后,所有文件都已下载。另一方面,任务仍然可以继续,所以你必须等待它们完成,这样的事情可能更适合第二种情况:

var tasks = photos.Select(  p => Task.Factory.StartNew(() =>
        {
            using(WebClient webClient = new WebClient())
            webClient.DownloadFile(p.src_big, string.Format(@"C:\pic{0}.jpg",p.ID));
        })).ToArray();
Task.WaitAll(tasks);

正如你所看到的Parallel.ForEach()在这种情况下更受欢迎,因为语法非常简洁,他们都使用线程池,所以选择你可以使用的最简单的选项,特别是因为你没有不需要增加复杂性。

此外,我认为您不会使用WebRequest更快地获取数据 - 大部分延迟都是由网络/互联网引起的,而不是您选择的两种 - 这就是我的情况选择更简单的代码,肯定是使用WebClient

总结一下:我选择Parallel.ForEach() WebClient,选项 1

答案 1 :(得分:0)

Asnwer到2是我正在使用相同的程序,它对我来说工作正常parallel.foreach减少了很多时间

当我分析静态时,我观察到如果我有大量的图片来获取然后parallel.foreach启动这么多的线程,它几乎达到我的宽带的cpapcity,就像我有最大的常规下载速度100kb /秒因此,下载图片达到100kb这意味着它无法比这更好,因为它是最重要的互联网