DrGriff
DrGriff

Reputation: 4916

Async call within a lambda foreach is not awaited

I have the following method that returns before it completes (method cut down for brevity):

private void ProcessAllItems(List<Item> items)
{
    items.ForEach(async item =>
    {
        var response = await Processor.IOBoundTaskAsync(item);
        // Some further processing on the response object.
    });
}

The Processor.IOBoundTaskAsync method returns a Task<SomeResponseObject>, so not a void.

So, what is happening?

I want the lambda foreach to process each item one at a time, so not in parallel. For the first iteration, the code goes into the IOBoundTaskAsync and gets as far as the first "await" (where it calls the first of 4 awaited web service methods) and then the calling method "ProcessAllItems" exits.

I'm only using test data, so my list only has 1 item in it.

What am I missing?

Upvotes: 3

Views: 1822

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149636

List<T>.ForEach converts your async lambda into async void, as it accepts an Action<T>. Although it does that and that has some complications with exception handling, your ForEach call should work properly. If not, you might not be using the async pattern correctly. I would advise you to set a breakpoint after the first await and see the continuation executing.

I would advise you to use a regular foreach instead:

private async Task ProcessAllItemsAsync(List<Item> items)
{
    foreach (var item in items)
    {
       var response = await Processor.IOBoundTaskAsync(item);
       // Some further processing on the response object.
    }
}

Read How can I use Async with ForEach? for more.

Upvotes: 8

Related Questions