我有一个异步函数,在其中必须对列表的每个元素进行异步调用。为此,我编写了这段代码:
List<string> batchItems;
batchItems.ForEach(async t => await SubmitBatchItemAsync(input, t));
但是,这不起作用:SubmitBatchItemAsync被调用,但是未等待。
为了使它正常工作,我不得不对此代码进行更改:
List<string> batchItems;
foreach (var batchItem in batchItems)
{
await SubmitBatchItemAsync(input, batchItem);
}
这也可以,但是不完全一样,因为Task.Wait()不能完全像await一样工作:
List<string> batchItems;
batchItems.ForEach(t => SubmitBatchItemAsync(input, t).Wait(CancellationToken.None));
有人知道为什么第一个选项不起作用,因为LINQ表达式支持等待吗? (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#async-lambdas)
ForEach
不支持async
。仅需要Action
即可对可枚举的每个项目执行。
因此,这意味着您的lambda表达式async t => await SubmitBatchItemAsync(input, t)
正像通常那样被转换为Func<T, Task>
;它正被转换为Action<T>
,强制为async void
。pitfalls of async void
methods之一是调用代码无法轻松确定何时完成。
TL; DR:有些API不支持async void
,在处理异步代码时应避免使用。 async
是这些API之一。
ForEach
有用: