使用異步Lambda的並行ForEach
並行處理集合的一種方法是使用帶有Lambda表達式的Parallel.ForEach
方法。但是,如果要在Lambda表達式中調用標記為異步的方法,則會遇到一些問題。
問題在於,Parallel.ForEach
創建的線程只是後台線程,該方法不會等待它們的完成。您可以在以下示例中看到這一點:
<code class="language-csharp">var bag = new ConcurrentBag<object>(); Parallel.ForEach(myCollection, async item => { // 预处理 var response = await GetData(item); bag.Add(response); // 后处理 }); var count = bag.Count;</code>
問題在於,count
將為 0,因為對 Parallel.ForEach
的調用不會等待 Lambda 完成。如果刪除 async
關鍵字,則該方法如下所示:
<code class="language-csharp">var bag = new ConcurrentBag<object>(); Parallel.ForEach(myCollection, item => { // 预处理 var responseTask = GetData(item); // 注意这里去掉了await responseTask.Wait(); var response = responseTask.Result; bag.Add(response); // 后处理 }); var count = bag.Count;</code>
這種方法有效,但是它禁用了 await
的優勢,並且需要您進行手動異常處理。
如何實現使用異步Lambda的Parallel.ForEach
有兩種方法可以實現使用 await
關鍵字的 Parallel.ForEach
循環:
1. 簡單並行化
此方法很簡單,只需要幾行代碼:
<code class="language-csharp">var bag = new ConcurrentBag<object>(); var tasks = myCollection.Select(async item => { // 预处理 var response = await GetData(item); bag.Add(response); // 后处理 }); await Task.WhenAll(tasks); var count = bag.Count;</code>
2. 複雜並行化
此方法比較複雜,但可以更好地控制並行化過程。有關詳細信息,請查看 Stephen Toub 的 ForEachAsync 文章。
以上是如何與`sync` lambdas與'parallel.foreach'正確使用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!