Parallel.ForEach 和 async-await [英] Parallel.ForEach and async-await
问题描述
我有这样的方法:
public async Task<MyResult> GetResult()
{
MyResult result = new MyResult();
foreach(var method in Methods)
{
string json = await Process(method);
result.Prop1 = PopulateProp1(json);
result.Prop2 = PopulateProp2(json);
}
return result;
}
然后我决定使用Parallel.ForEach
:
public async Task<MyResult> GetResult()
{
MyResult result = new MyResult();
Parallel.ForEach(Methods, async method =>
{
string json = await Process(method);
result.Prop1 = PopulateProp1(json);
result.Prop2 = PopulateProp2(json);
});
return result;
}
但现在我有一个错误:
异步模块或处理程序已完成,而异步操作仍处于挂起状态.
An asynchronous module or handler completed while an asynchronous operation was still pending.
推荐答案
async
不适用于 ForEach
.特别是,您的 async
lambda 正在转换为 async void
方法.有许多 避免async void
的原因(正如我在 MSDN 文章中所描述的);其中之一是您无法轻松检测 async
lambda 何时完成.ASP.NET 将看到您的代码在未完成 async void
方法的情况下返回并(适当地)抛出异常.
async
doesn't work well with ForEach
. In particular, your async
lambda is being converted to an async void
method. There are a number of reasons to avoid async void
(as I describe in an MSDN article); one of them is that you can't easily detect when the async
lambda has completed. ASP.NET will see your code return without completing the async void
method and (appropriately) throw an exception.
您可能想做的是并发处理数据,而不是并行.ASP.NET 上几乎不应该使用并行代码.下面是异步并发处理的代码:
What you probably want to do is process the data concurrently, just not in parallel. Parallel code should almost never be used on ASP.NET. Here's what the code would look like with asynchronous concurrent processing:
public async Task<MyResult> GetResult()
{
MyResult result = new MyResult();
var tasks = Methods.Select(method => ProcessAsync(method)).ToArray();
string[] json = await Task.WhenAll(tasks);
result.Prop1 = PopulateProp1(json[0]);
...
return result;
}
这篇关于Parallel.ForEach 和 async-await的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!