我有一个listOfFilesToDownload
。我想并行下载列表中的所有文件
.........
Parallel.ForEach(listOfFilesToDownload, (file) =>
{
SaveFile(file, myModel);
});
private static void SaveFile(string file, MyType myModel)
{
filePath = "...";
try
{
using (WebClient webClient = new WebClient())
{
webClient.DownloadFileTaskAsync(file, filePath)
}
//some time consuming proccess with downloaded file
}
catch (Exception ex)
{
}
}
在SaveFile
方法中我下载了文件,然后我想等到它被下载,然后对这个文件做一些处理,等到这个处理完成。完整的迭代必须是 - 下载文件并处理它
所以,问题是:
DownloadFile
,它将阻塞线程直到文件下载,我认为这不太好)webClient.DownloadFileCompleted
事件并在那里处理文件,但我没有设法确保处理完成,示例如下)立>
复杂的问题是如何等待文件异步下载并等到它被处理
using (WebClient webClient = new WebClient())
{
webClient.DownloadFileCompleted += DownloadFileCompleted(filePath, myModel);
webClient.DownloadFileTaskAsync(file, filePath);
}
DownloadFileCompleted 返回 AsyncCompletedEventHandler:
public static AsyncCompletedEventHandler DownloadFileCompleted(string filePath, MyType myModel)
{
Action<object, AsyncCompletedEventArgs> action = (sender, e) =>
{
if (e.Error != null)
return;
//some time consuming proccess with downloaded file
};
return new AsyncCompletedEventHandler(action);
}
非常感谢!
答案 0 :(得分:1)
你考虑过 Task.WhenAll 吗?类似的东西:
var tasks = listOfFilesToDownload
.AsParallel()
.Select(f => SaveFile(f, myModel))
.ToList();
await Task.WhenAll(tasks);
private static async Task SaveFile(string file, MyType myModel)
{
filePath = "...";
using (WebClient webClient = new WebClient())
{
await webClient.DownloadFileTaskAsync(file, filePath);
// process downloaded file
}
}
如果您在下载文件后正在进行 CPU 密集型工作,则 .AsParallel() 调用会很有帮助。否则你最好没有它。
答案 1 :(得分:0)
如 this answer 所述,Parallel.ForEach() 背后的整个想法是您有一组线程,每个线程处理集合的一部分,因此您不能等待保存部分完成。您可以做的是使用 Dataflow 而不是 Parallel.ForEach,后者很好地支持异步任务。
像这样:
var downloadTasks = listOfFilesToDownload.Select(file =>
{
SaveFile(file, myModel);
});
var downloaded = await Task.WhenAll(customerTasks);
等待所有文件保存完毕。
同一问题的其他答案可能对您有用。