这段代码工作正常:
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() ?
最佳答案
你是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。
关于c# - Parallel.ForEach 中的 WebClient.DownloadFile(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5466680/