3

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?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
DrGriff
  • 4,394
  • 9
  • 43
  • 92

1 Answers1

8

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.

Community
  • 1
  • 1
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321