C# Parallel.ForEach的终结器

C# Parallel.ForEach的终结器,c#,.net,multithreading,C#,.net,Multithreading,如何添加在所有并行完成后运行的终结器 Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, async (entry) => // Do something with the entry. }); 我试过这样做,但没有编译: Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }

如何添加在所有并行完成后运行的终结器

Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, async (entry) =>
    // Do something with the entry.
});
我试过这样做,但没有编译:

Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, async (entry) =>
    // Do something with the entry.
}, () => { // Was hoping this would work. });

你什么都不用做。您的
Parallel.ForEach
将一直运行,直到所有线程完成其工作。这是
Parallel.Foreach()
的一个非常好的优点


所以就在
Parallel.ForEach(()=>{/*code*/})之后所有线程都将完成。

您无需执行任何操作。您的
Parallel.ForEach
将一直运行,直到所有线程完成其工作。这是
Parallel.Foreach()
的一个非常好的优点

所以就在
Parallel.ForEach(()=>{/*code*/})之后所有线程都将完成


  • 您应该而不是
    Parallel.ForEach
    的操作声明为
    async
    。如果在该操作中使用
    wait
    ,则控制流将返回到
    Parallel.ForEach
    ,其实现“认为”该操作已完成。这将导致与您预期的行为截然不同的行为


  • 循环完成后,
    Parallel.ForEach
    的调用返回。对枚举中的所有元素执行所有操作后返回。因此,“当所有并行完成”后,您想做的任何事情都可以在调用之后立即完成:

    Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, 
             (entry) =>
             // Do something with the entry.
    );
    DoSomethingWhenAllParallelsHaveCompleted();
    

  • 您应该而不是
    Parallel.ForEach
    的操作声明为
    async
    。如果在该操作中使用
    wait
    ,则控制流将返回到
    Parallel.ForEach
    ,其实现“认为”该操作已完成。这将导致与您预期的行为截然不同的行为


  • 循环完成后,
    Parallel.ForEach
    的调用返回。对枚举中的所有元素执行所有操作后返回。因此,“当所有并行完成”后,您想做的任何事情都可以在调用之后立即完成:

    Parallel.ForEach(entries, new ParallelOptions { MaxDegreeOfParallelism = 15 }, 
             (entry) =>
             // Do something with the entry.
    );
    DoSomethingWhenAllParallelsHaveCompleted();
    

  • 正如我和其他人在注释
    Parallel.ForEach
    中提到的那样,它不支持异步函数,原因是当您执行
    async(entry)=>…
    时,它与

    Parallel.ForEach(entries, Example);
    
    //elsewhere
    async void Example(Entry entry)
    {
       ...
    }
    
    由于函数是
    async void
    ForEach
    无法判断函数何时“完成”,因此当您点击第一个
    wait
    而不是任务完成时,它会认为函数已完成

    解决这个问题的方法是使用一个支持异步函数的库,这是一个很好的方法。您可以通过将NuGet包安装到项目中来获得它。您可以将以前的代码重新创建为

    private const int MAX_PARALLELISM = 15
    
    public async Task ProcessEntries(IEnumerable<Entry> entries)
    {
        var block = new ActionBlock<Entry>(async (entry) => 
                                           {
                                               //This is now a "async Task" instead of a async void
                                           }, 
                                           new ExecutionDataflowBlockOptions 
                                           { 
                                               MaxDegreeOfParallelism = MAX_PARALLELISM
    
                                           });
        foreach(var entry in entries)
        {
            await block.SendAsync(entry);
        }
    
        block.Complete();
        await block.Completion;
    
        DoExtraWorkWhenDone();
    }
    
    private const int MAX_PARALLELISM=15
    公共异步任务ProcessEntries(IEnumerable条目)
    {
    变量块=新操作块(异步(条目)=>
    {
    //这现在是一个“异步任务”,而不是异步任务
    }, 
    新的ExecutionDataflowBlockOptions
    { 
    MaxDegreeOfParallelism=最大并行度
    });
    foreach(分录中的var分录)
    {
    wait block.SendAsync(条目);
    }
    block.Complete();
    等待区块完成;
    DoExtraWorkWhenDone();
    }
    
    正如我和其他人在评论
    Parallel中提到的那样。ForEach
    不支持异步函数,原因是当您执行
    异步(条目)=>…
    时,与

    Parallel.ForEach(entries, Example);
    
    //elsewhere
    async void Example(Entry entry)
    {
       ...
    }
    
    由于函数是
    async void
    ForEach
    无法判断函数何时“完成”,因此当您点击第一个
    wait
    而不是任务完成时,它会认为函数已完成

    解决这个问题的方法是使用一个支持异步函数的库,这是一个很好的方法。您可以通过将NuGet包安装到项目中来获得它。您可以将以前的代码重新创建为

    private const int MAX_PARALLELISM = 15
    
    public async Task ProcessEntries(IEnumerable<Entry> entries)
    {
        var block = new ActionBlock<Entry>(async (entry) => 
                                           {
                                               //This is now a "async Task" instead of a async void
                                           }, 
                                           new ExecutionDataflowBlockOptions 
                                           { 
                                               MaxDegreeOfParallelism = MAX_PARALLELISM
    
                                           });
        foreach(var entry in entries)
        {
            await block.SendAsync(entry);
        }
    
        block.Complete();
        await block.Completion;
    
        DoExtraWorkWhenDone();
    }
    
    private const int MAX_PARALLELISM=15
    公共异步任务ProcessEntries(IEnumerable条目)
    {
    变量块=新操作块(异步(条目)=>
    {
    //这现在是一个“异步任务”,而不是异步任务
    }, 
    新的ExecutionDataflowBlockOptions
    { 
    MaxDegreeOfParallelism=最大并行度
    });
    foreach(分录中的var分录)
    {
    wait block.SendAsync(条目);
    }
    block.Complete();
    等待区块完成;
    DoExtraWorkWhenDone();
    }
    
    Parallel.ForEach无法正常工作当您执行
    async(entry)=>
    时,请不要对其使用异步方法。您必须使用非异步方法或切换到类似的东西。
    并行。ForEach
    对于返回任务的函数没有重载,因此您的异步函数将立即返回,迭代将立即完成。请参阅.Parallel.ForEach在执行
    async(entry)=>
    时无法正常工作,请不要对其使用异步方法。您必须使用非异步方法或切换到类似的东西。
    并行。ForEach
    对于返回任务的函数没有重载,因此您的异步函数将立即返回,迭代将立即完成。看,那我怎么在行动中等待呢?我需要使用一个
    HttpClient
    来发送数据,它上面有一个
    SendAsync
    方法。@Alexandru您需要使用
    .Wait()
    .Result
    。你能举个例子吗
    .Result
    可能会死锁,我不确定
    .Wait()
    是否能保证结果