Reputation: 29
I have an async function where I must make an async call for each of the elements of a list. To do this, I have written this piece of code:
List<string> batchItems;
batchItems.ForEach(async t => await SubmitBatchItemAsync(input, t));
However, this is not working: the SubmitBatchItemAsync is invoked, but it is not awaited.
I had to change this code to this to make it work:
List<string> batchItems;
foreach (var batchItem in batchItems)
{
await SubmitBatchItemAsync(input, batchItem);
}
This also works, but it is not exactly the same, as Task.Wait() does not work exactly as await does:
List<string> batchItems;
batchItems.ForEach(t => SubmitBatchItemAsync(input, t).Wait(CancellationToken.None));
Does anyone know why the first option is not working, as LINQ expressions support await? ( https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#async-lambdas )
Upvotes: 2
Views: 515
Reputation: 43474
You may find useful this extension method for List
s:
public static async Task ForEachAsync<T>(this List<T> source, Func<T, Task> function)
{
foreach (var item in source)
{
await function(item);
}
}
Usage example:
await batchItems.ForEachAsync(async t => await SubmitBatchItemAsync(input, t));
TBH this is not as useful as it seems, because when dealing with asynchronous operations you usually want to launch them with some level of concurrency, not the one after the completion of the other.
Upvotes: 1
Reputation: 456437
ForEach
is not async
-aware. It only takes an Action
to execute on each item of the enumerable.
So this means your lambda expression async t => await SubmitBatchItemAsync(input, t)
is not being converted into a Func<T, Task>
like it would normally be; it's being converted into an Action<T>
, forcing it to be async void
.
And one of the pitfalls of async void
methods is that calling code can't easily determine when they complete.
TL;DR: There are some APIs that are not async
-aware, and should just be avoided when working with asynchronous code. ForEach
is one of these APIs.
Upvotes: 5