C# 如何等待并行Linq操作完成
我不确定我应该如何混合plinq和async Wait。假设我有以下接口C# 如何等待并行Linq操作完成,c#,linq,task-parallel-library,async-await,parallel-extensions,C#,Linq,Task Parallel Library,Async Await,Parallel Extensions,我不确定我应该如何混合plinq和async Wait。假设我有以下接口 public interface IDoSomething ( Task Do(); } 我有一个清单,我想并行执行,并能等待所有的完成 public async Task DoAll(IDoSomething[] doers) { //Execute all doers in parallel ideally using plinq and //continue when all are co
public interface IDoSomething (
Task Do();
}
我有一个清单,我想并行执行,并能等待所有的完成
public async Task DoAll(IDoSomething[] doers) {
//Execute all doers in parallel ideally using plinq and
//continue when all are complete
}
如何实现这一点?我不知道如何从并行linq到任务,反之亦然
我并不十分担心异常处理。理想情况下,第一个会触发并破坏整个过程,因为我计划在出错时丢弃整个过程
编辑:很多人都在说Task.WaitAll。我知道这一点,但我的理解是,除非有人能够证明,否则它不会主动地将事情并行化到多个可用的处理器核心。我特别要问的是两个问题-
若我在Plinq操作中等待一个任务,那个么它是否会因为调度了一个新线程而失去很多优势
如果我doers.AsParallel.ForAllasync d=>wait d.Do平均需要5秒钟,那么在此期间如何不旋转调用线程
您要找的是:
public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
return Task.WhenAll(doers.Select(doer => Task.Run(() => doer.Do())));
}
否则,不需要并行性,您可以使用Task.whalll并发启动异步操作并等待所有返回的任务:
当问到并行异步代码问题时,正确的答案通常是TPL数据流。但是一个简单的Task.whalll和Task.Runs结合起来就足够了,就像@l3arnon的回答一样。@GeorgeMauer:plink用于并行化CPU限制的工作。Async/await用于并发异步工作,通常是I/O绑定的。异步等待并行工作完成等待任务是有意义的。Run=>{/*parallel stuff*/},但尝试将异步工作(通常是I/O绑定的工作)并行化的意义要小得多。WhenAll本身可以为您提供异步并发,或者WhenAll wrapping Task.Runs可以为您提供一种异步并行foreach。乔治马勒:顺便说一句,我尽量不在这里做自我宣传,但我真的认为你会从中受益。我处理并发、异步、并行、TPL数据流、Rx以及它们如何一起工作。90%的可能重复确保这将异步连接所有内容,但默认情况下,执行者不会并行运行。这是因为异步不是并行。除非有什么特别告诉TPL为此使用并行性。对吗?我的意思是,除非TPL专门有一个调度程序来执行并行线程,否则它一次只运行一个,尽管异步方式类似于javascript。好的,那么使用Task.Run将其强制放入线程池或默认调度程序将其发送到的任何位置运行…那么像这样的操作与使用AsParallel有什么区别呢?你必须理解为什么我对那些似乎忽略了一半问题的答案持怀疑态度。@GeorgeMauer plinq比async await老,因此不能处理异步方法。你可以用阿斯帕莱尔,但那又怎么样?plinq的答案是使用ForAll,但它不能接受异步委托,也不会返回等待的任务。异步方式是Task.Run和Task.whalll,问题的任何部分都不会被忽略。@GeorgeMauer我看到你已经在一个ForAll选项中编辑了你的问题。这将创建一个非常危险的异步void lambda表达式:@GeorgeMauer TPL是异步wait和PLinq以及TPL数据流和其他数据流的下划线框架。PLinq是一种并行处理解决方案。async await是异步编程的一个更好的解决方案,比以前的选项(例如BeginX和EndX)要好。在大多数情况下,他们没有共同之处。在你的生活中,他们可能有,但他们不适合在一起。您可以看看TPL数据流和反应式扩展,它们是在考虑异步的情况下构建的,可以填补PLinq留下的漏洞。好的,谢谢,这开始为我完成这张图片。
public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
return Task.WhenAll(doers.Select(doer => Task.Run(() => doer.Do())));
}
async Task Do()
{
for (int i = 0; i < 10000; i++)
{
Math.Pow(i,i);
}
await Task.Delay(10000);
}
public Task DoAllAsync(IEnumerable<IDoSomething> doers)
{
return Task.WhenAll(doers.Select(doer => doer.Do()));
}