Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Task.StartNew Parallel.ForEach不';不要等待_C#_.net_Async Await_Task Parallel Library - Fatal编程技术网

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,在哪里可以学习它?