2016-08-23 48 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