C# Task.StartNew Parallel.ForEach不';不要等待
我有以下代码:C# Task.StartNew Parallel.ForEach不';不要等待,c#,.net,async-await,task-parallel-library,C#,.net,Async Await,Task Parallel Library,我有以下代码: await Task.Factory.StartNew( () => Parallel.ForEach( urls, new ParallelOptions { MaxDegreeOfParallelism = 2 }, async url => { Uri uri = new Uri(url); string filename = System.IO.
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多个元素的列表,但它不会等待下载和文件写入完成。
事实上,他开始下载和写作,显示信息,然后在后台继续下载。。。
我需要下载大量并行和异步的文件,但我必须等待它们全部下载。此代码有什么问题?并行。ForEach不能与async一起工作。它需要一个
操作
,但为了等待异步方法,它需要得到一个Func
您可以使用TPL数据流的ActionBlock
,它是在考虑异步的情况下构建的。您给它一个委托(异步或非异步)来执行每个项目。您可以配置块的并行性(必要时还可以配置有界容量)。并将您的项目发布到其中:
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
var block=newactionblock(异步url=>
{
Uri=新的Uri(url);
字符串filename=System.IO.Path.GetFileName(uri.LocalPath);
使用(HttpClient=new HttpClient())
使用(HttpResponseMessage response=wait client.GetAsync(url))
使用(HttpContent=response.content)
{
//…读字符串。
使用(var fileStream=newfilestream(config.M_F_P+filename,FileMode.Create,FileAccess.Write))
{
等待内容。CopyToAsync(文件流);
}
}
},新的ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=2});
foreach(url中的变量url)
{
block.Post(url);
}
block.Complete();
等待区块完成;
//完成
它表示此命名空间中不存在ActionBlock。如果我尝试使用System.Threading.Tasks.Dataflow导入它,它会说Dataflow不存在。我能做什么?@giogiowefj这是一个nuget,不是“传统的.net框架”的一部分。你可以在这里找到它:好吧,现在它运行了,但它仍然不会等待所有的事情都完成completed@giogiowefj您需要等待块使用其Completion
属性完成,正如您在我的答案中所看到的。哦,没有看到它,您编辑了答案吗?有了它,一切都很好!非常感谢你!但我还是不明白为什么我不能使用我的代码。我一生中从未见过ActionBlock,在哪里可以学习它?