我遇到了这段代码:
items.ForEach(async item =>
{
doSomeStuff();
await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo);
await AddBlah(SqlMumboJumbo);
});
将这个.forEach委托制作成是否有任何意义,或者它只是一个正常的foreach循环?只要包含循环的函数是异步的,默认情况下这是异步的吗?
答案 0 :(得分:7)
ForEach
收到的代表是Action<T>
:
public void ForEach(Action<T> action)
这意味着,您在其中使用的任何异步委托都将有效地转换为async void
方法。这些是“火与忘记”。执行方式。这意味着你的foreach不会在继续调用列表中下一个项目的委托之前完成异步等待,这可能是一个不受欢迎的行为。
改为使用常规foreach
。
旁注 - Eric Lippert撰写的foreach VS ForEach,很棒的博文。
答案 1 :(得分:2)
您不知道您的功能何时结束,也不知道该功能的结果。如果您在单独的任务中开始每个计算,您可以等待Task.WhenAll并解释结果,甚至捕获异常:
private async Task ActionAsync(T item)
{
doSomeStuff();
await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo);
await AddBlah(SqlMumboJumbo);
}
private async Task MyFunction(IEnumerable<T> items)
{
try
{
foreach (var item in items)
{
tasks.Add( ActionAsync(item) )
}
// while all actions are running do something useful
// when needed await for all tasks to finish:
await Task.WhenAll(tasks);
// interpret the result of each action using property Task.Result
}
catch (AggregateException exc)
{
ProcessAggregateException(exc);
}
}
当任何任务抛出异常时,抛出aggregateException。如果包含所有任务抛出的所有异常。