2013-02-28 49 views
52

我想並行處理一個集合,但是我在實現它時遇到了問題,因此我希望得到一些幫助。與異步lambda平行的foreach

如果我想在並行循環的lambda內調用C#中標記爲異步的方法,則會出現問題。例如:

var bag = new ConcurrentBag<object>(); 
Parallel.ForEach(myCollection, async item => 
{ 
    // some pre stuff 
    var response = await GetData(item); 
    bag.Add(response); 
    // some post stuff 
} 
var count = bag.Count; 

與計數爲0時出現問題,因爲創建的所有線程都有效只是後臺線程和Parallel.ForEach調用不會等待完成。如果我刪除async關鍵字,方法如下:

var bag = new ConcurrentBag<object>(); 
Parallel.ForEach(myCollection, item => 
{ 
    // some pre stuff 
    var responseTask = await GetData(item); 
    responseTask.Wait(); 
    var response = responseTask.Result; 
    bag.Add(response); 
    // some post stuff 
} 
var count = bag.Count; 

它的工作原理,但它完全禁用等待聰明,我必須做一些手工異常處理。(除去簡潔)。

如何實現在lambda中使用await關鍵字的Parallel.ForEach循環?可能嗎?

Parallel.ForEach方法的原型需要Action<T>作爲參數,但我希望它等待我的異步lambda。

+0

我假設你的意思是刪除'await'從'伺機的GetData(項目)'在你的第二個代碼塊,因爲它會產生一個編譯錯誤的-is。 – 2017-11-30 12:18:23

+0

[Parallel.ForEach中嵌套等待]的可能重複(https://stackoverflow.com/questions/11564506/nesting-await-in-parallel-foreach) – 2017-12-02 20:57:50

回答

76

如果你只是想簡單的並行性,你可以這樣做:

var bag = new ConcurrentBag<object>(); 
var tasks = myCollection.Select(async item => 
{ 
    // some pre stuff 
    var response = await GetData(item); 
    bag.Add(response); 
    // some post stuff 
}); 
await Task.WhenAll(tasks); 
var count = bag.Count; 

如果你需要更復雜的東西,檢查出Stephen Toub's ForEachAsync post

+18

可能需要一個節流機制。這將立即創建儘可能多的任務,因爲有可能以10k網絡請求等爲結果的項目。 – usr 2013-02-28 13:32:37

+4

@usr Stephen Toub文章中的最後一個例子解決了這個問題。 – svick 2013-02-28 23:09:44

+0

@svick我對最後一個樣本感到困惑。在我看來,它只是分批執行一些任務來爲我創建更多任務,但他們都開始大規模開始。 – 2017-06-12 16:33:45

14

您可以從AsyncEnumerator NuGet Package使用ParallelForEachAsync擴展方法:

using System.Collections.Async; 

var bag = new ConcurrentBag<object>(); 
await myCollection.ParallelForEachAsync(async item => 
{ 
    // some pre stuff 
    var response = await GetData(item); 
    bag.Add(response); 
    // some post stuff 
}, maxDegreeOfParallelism: 10); 
var count = bag.Count; 
+0

這是你的包?我看到你現在在幾個地方張貼這個? :D哦,等等..你的名字在包裹上:D +1 – ppumkin 2017-03-14 14:47:39

+5

@ppumkin,是的,它是我的。我一遍又一遍地看到這個問題,所以決定儘可能以最簡單的方式解決它,並讓其他人免於掙扎以及:) – 2017-03-14 15:51:02

+0

謝謝..它絕對有意義,幫助我度過了美好的時光! – ppumkin 2017-03-14 16:03:07