使用异步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中文网其他相关文章!