如何等待Parallel Linq操作完成
本文关键字:Linq 操作 Parallel 何等待 等待 | 更新日期: 2023-09-27 18:27:50
我不确定应该如何混合plinq和async-await
。假设我有以下接口
public interface IDoSomething (
Task Do();
}
我有一个清单,我想并行执行,并能够await
完成所有这些。
public async Task DoAll(IDoSomething[] doers) {
//Execute all doers in parallel ideally using plinq and
//continue when all are complete
}
如何实现?我不知道如何从并行linq到任务,反之亦然。
我并不十分担心异常处理。理想情况下,第一个会触发并破坏整个过程,因为我计划在出现错误时放弃整个过程。
编辑:很多人都在说Task.WaitAll
。我知道这一点,但我的理解(除非有人能证明)是,它不会主动将事情并行到多个可用的处理器核心。我特别想问的是双重问题——
如果我在Plinq操作中
await
和Task
,这是否消除了很多优点,因为它调度了一个新线程?如果我
doers.AsParallel().ForAll(async d => await d.Do())
(平均耗时约5秒),如何在这期间不旋转调用线程?
您想要的是:
public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
return Task.WhenAll(doers.Select(doer => Task.Run(() => doer.Do())));
}
使用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);
}
否则,就不需要并行性,只需同时启动异步操作,然后使用Task.WhenAll
:等待所有返回的任务
public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
return Task.WhenAll(doers.Select(doer => doer.Do()));
}
public async Task DoAll(IDoSomething[] doers) {
//using ToArray to materialize the query right here
//so we don't accidentally run it twice later.
var tasks = doers.Select(d => Task.Run(()=>d.Do())).ToArray();
await Task.WhenAll(tasks);
}