2

我想知道什么是并行执行多个异步方法的推荐方式?ActionBlock <T> vs Task.WhenAll

在System.Threading.Tasks.Dataflow中,我们可以指定最大并行度,但无界可能是Task.WhenAll的默认值?

这样的:

var tasks = new List<Task>(); 
foreach(var item in items) 
{ 
    tasks.Add(myAsyncMethod(item)); 
} 
await Task.WhenAll(tasks.ToArray()); 

,或者:

var action = new ActionBlock<string>(myAsyncMethod, new ExecutionDataflowBlockOptions 
     { 
      MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, 
      BoundedCapacity = DataflowBlockOptions.Unbounded, 
      MaxMessagesPerTask = DataflowBlockOptions.Unbounded 
     }); 
foreach (var item in items) { } 
{ 
    action.Post(item); 
} 
action.Complete(); 

await action.Completion; 
+0

'Parallel.ForEach()'? –

+1

并行和异步混合不好,并且这些方法是异步的(我无法更改它们) –

+1

您显示的'Task.WhenAll'代码与并行执行任务无关 - 任何有关使用例如线程池线程,并行等等,都发生在'myAsyncMethod'里面(大概是)返回热的Task。 –

回答

1

我想知道什么是并行执行多个异步方法的推荐方式?

边注:实际上不是平行,但并发

在System.Threading.Tasks.Dataflow中,我们可以指定最大并行度,但无界可能是Task.WhenAll的默认值?

正如有人评论,Task.WhenAll只加入现有的任务;当你的代码到达Task.WhenAll时,所有的并发性判断已经完成。

您可以通过使用诸如SemaphoreSlim之类的东西来节制纯异步代码。

决定是直接使用异步并发还是TPL数据流取决于周围的代码。如果这个并发操作只是异步调用一次,那么异步并发是最好的选择;但如果此并发操作是数据的“管道”的一部分,那么TPL Dataflow可能更适合。

0

这两种方法是可以接受的选择应该由你的要求来管理,你可以看到数据流给你很多的可配置性,你会否则必须直接使用任务时手动实现。

请注意,在这两种情况下,任务池将负责排队和运行任务,因此相同的行为应该保留相同的行为。

数据流擅长将可组合的异步操作组链接在一起,而使用任务为您提供更细粒度的控制。

+0

好吧,如果只是为了并行而不把它链接成没有真正的好处? –

+0

如果你不需要链接或组合,它可能会过度杀伤,是的 – Slugart