此代码可以正常工作:
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()?
答案 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这意味着它无法比这更好,因为它是最重要的互联网