Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.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# 如何等待并行Linq操作完成_C#_Linq_Task Parallel Library_Async Await_Parallel Extensions - Fatal编程技术网

C# 如何等待并行Linq操作完成

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

我不确定我应该如何混合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 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()));
}