2016-08-23 29 views
2

我有可能需要运行几千个独立的任务。他们每个人都可能进行数据库调用,所以他们已经在可能的情况下利用异步。也就是说,如果我想让他们全部平行运行,那么最好的方法是什么?最好的方式来并行启动几个异步任务?

我有了这个目前:

List<Task> tasks = new List<Task>(); 
for(var i = 0; i < items.Count; ++i) tasks.Add(PerformTask()); 
await Task.WhenAll(tasks); // or possibly Task.WaitAll(tasks.ToArray()) 

是否有这样做的客观最好的方法:

Parallel.For(0, items.Count, async _ => await PerformTask()); 

我还用考虑?

编辑:这是不同于标记的重复问题,因为我没有问差异。我在问我的用例是哪种方式是正确的。

+1

[Parallel.ForEach vs Task.Run and Task.WhenAll](http://stackoverflow.com/questions/19102966/parallel-foreach-vs-task-run-and-task-whenall) – Liam

+0

for最后一部分'Task.WhenAll'可能更可取,因为它会返回一个任务。 'Task.WaitAll'返回void,并将阻塞直到全部完成。 – Jonesopolis

+0

@Liam,不重复,请参阅编辑。链接答案的答案实际上没有说明在特定情况下应该使用什么。而且似乎并没有一套“只有这样做”的答案。 – Charles

回答

1

Parallel不是一个选项,因为您有异步操作。

的选项有:

  • 开始的同时任务的所有,然后用await Task.WhenAll它们全部完成。如果您发现需要限制活动任务的数量,则可以使用SemaphoreSlim
  • 使用ActionBlock<T>(来自TPL Dataflow)单独排队工作。如果您想同时处理多个数据,则可以使用ExecutionDataflowBlockOptions.MaxDegreeOfParallelism

ActionBlock<T>方法会更好,如果你不知道所有在他们开始(即,如果有更多的可以当你到达处理),或者如果时间任务的其他部位附近的代码将适用于“管道”类设计。

Task.WhenAll是不错的,因为它不需要一个单独的库有自己的设计理念和学习曲线。

要么Task.WhenAll要么ActionBlock<T>适合您的使用情况。

+0

在我的情况下,我知道所有将要运行的任务,所以'ActionBlock '我放弃了它的优势。总的来说,每个任务的处理时间都非常短,直到数据库调用。我对分配给我的查询池很满意,所以我会坚持使用'Task.WhenAll'。谢谢! – Charles