我有这个代码:
await Task.Factory.StartNew(
() => Parallel.ForEach(
urls,
new ParallelOptions { MaxDegreeOfParallelism = 2 },
async url =>
{
Uri uri = new Uri(url);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(url))
using (HttpContent content = response.Content)
{
// ... Read the string.
using (var fileStream = new FileStream(config.M_F_P + filename, FileMode.Create, FileAccess.Write))
{
await content.CopyToAsync(fileStream);
}
}
}));
MessageBox.Show("Completed");
它应该处理超过 800 个元素的列表,但它不会等待下载和文件写入完成。 事实上,他开始下载和写入,显示消息,然后在后台继续下载...... 我需要并行和异步下载很多文件,但我必须等待所有文件下载完毕。这段代码有什么问题?
最佳答案
Parallel.ForEach
不适用于异步。它需要一个 Action
但为了等待异步方法,它需要获得 Func<Task>
.
您可以使用 TPL 数据流的 ActionBlock
那是在考虑异步的情况下构建的。您给它一个委托(delegate)(异步或非异步)来执行每个项目。您可以配置 block 的并行性(如果需要,还可以配置有限的容量)。然后将您的项目发布到其中:
var block = new ActionBlock<string>(async url =>
{
Uri uri = new Uri(url);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(url))
using (HttpContent content = response.Content)
{
// ... Read the string.
using (var fileStream = new FileStream(config.M_F_P + filename, FileMode.Create, FileAccess.Write))
{
await content.CopyToAsync(fileStream);
}
}
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 } );
foreach (var url in urls)
{
block.Post(url);
}
block.Complete();
await block.Completion;
// done
关于c# - Task.StartNew Parallel.ForEach 不等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34843224/