如何等待并行Linq操作完成

Geo*_*uer 1 c# linq parallel-extensions task-parallel-library async-await

我不确定我应该如何混合plinq和async-await.假设我有以下界面

public interface IDoSomething (
    Task Do();
}
Run Code Online (Sandbox Code Playgroud)

我有一个列表,我想并行执行,并能够await完成所有这些.

public async Task DoAll(IDoSomething[] doers) {
    //Execute all doers in parallel ideally using plinq and 
    //continue when all are complete
}
Run Code Online (Sandbox Code Playgroud)

怎么实现这个?我不知道如何从并行linq转到任务,反之亦然.

我对异常处理并不十分担心.理想情况下,第一个会触发并打破整个过程,因为我打算在出错时抛弃整个过程.

编辑:很多人都说Task.WaitAll.我知道这一点,但我的理解(除非有人能证明不是这样)是因为它不能主动将你的东西并行化到多个可用的处理器核心.我特别要问的是双重的 -

  1. 如果我await一个Task一个PLINQ行动中确实是摆脱由于日程安排一个新的线程有很多的优势的?

  2. 如果我doers.AsParallel().ForAll(async d => await d.Do())平均需要大约5秒钟,那么在此期间我怎么不旋转调用线程呢?

i3a*_*non 7

您正在寻找的是:

public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
    return Task.WhenAll(doers.Select(doer => Task.Run(() => doer.Do())));
}
Run Code Online (Sandbox Code Playgroud)

使用Task.Run将使用一个ThreadPool线程来执行的每个同步部分async方法Do在并行而Task.WhenAll异步地等待异步部分一起被同时执行.


只有在这些async方法中具有大量同步部件(await例如,之前的部件)时,这是一个好主意,例如:

async Task Do()
{
    for (int i = 0; i < 10000; i++)
    {
        Math.Pow(i,i);
    }

    await Task.Delay(10000);
}
Run Code Online (Sandbox Code Playgroud)

否则,不需要并行性,您可以同时触发异步操作并等待所有返回的任务Task.WhenAll:

public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
    return Task.WhenAll(doers.Select(doer => doer.Do()));
}
Run Code Online (Sandbox Code Playgroud)