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
  • 95,331
  • 80
  • 293
  • 426
DrGriff
  • 4,040
  • 6
  • 36
  • 81

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
  • 141,979
  • 28
  • 246
  • 306