C# get results from Task.WhenAll

The C# method Task.WhenAll can run a bunch of async methods in parallel and returns when every one finished.

But how do you collect the return values?

UPDATED 2023-02-15: Updated code based on comments. Thx for all the suggestions.

Imagine that you have this pseudo-async-method:

private async Task<int> GetAsync(int number)
{
  await Task.Delay(number * 100);
  return number;
}

And you wish to call that method 20 times, and then collect all the results in a list?

That is a 3 step rocket:

  1. Create a list of tasks to run
  2. Run the tasks in parallel using Task.WhenAll.
  3. Iterate over the results
// Create a list of tasks to run
List<Task<int>> tasks = new List<Task<int>>();
for (int i = 0; i < 20; i++)
{
  tasks.Add(GetAsync(i));
}

// Run the tasks in parallel, and
// wait until all have been run
IEnumerable<int> results = await Task.WhenAll(tasks);

// Iterate over the results
foreach (var result in results)
{
  Console.WriteLine(result);
}

WHY DID I UPDATE THE CODE?

In my previous example, I forgot to include the return type when creating the list of tasks:

// WRONG:
// I did this:
List<Task> tasks = new List<Task>();

// CORRECT:
// But I should have done this:
List<Task<int>> tasks = new List<Task<int>>();

When you do not include the type that the task returns, the Task.WhenAll returns void, and you need another loop to collect the return types directly from the tasks themselves.

Thanks for all the comments. And happy coding.

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in General .NET. Bookmark the permalink.

6 Responses to C# get results from Task.WhenAll

  1. Michael Shedden says:

    // This is a bit nicer (and shorter) I think

    // Create a list of tasks to run
    List<Task> tasks = new List<Task>();
    foreach (int i=0;i<20;i++)
    {
    tasks.Add(GetAsync(i));
    }

    // Run the tasks in parallel, and
    // wait until all have been run
    // collecting the results at the same time
    var results = await Task.WhenAll(tasks);

    // the above is an array, but if a list is required this line could be used instead:
    // var results = (await Task.WhenAll(tasks)).ToList();

    Like

  2. Michael Shedden says:

    // This is a bit nicer (and shorter) I think – my previous posting
    // looked like the Task lost its generic parameter, string

    // Create a list of tasks and start them running
    List<Task> tasks = new List<Task>();
    foreach (int i=0;i<20;i++)
    {
    tasks.Add(GetAsync(i));
    }

    // Wait until the running tasks have been run
    // collecting the results at the same time
    var results = await Task.WhenAll(tasks);

    // the above is an array, but if a list is required this line could be used instead:
    // var results = (await Task.WhenAll(tasks)).ToList();

    Like

  3. Sergey says:

    Task.WhenAll does not run tasks!!
    But for collecting all the results in one array, it is fine.
    var results = await Task.WhenAll(tasks);

    Like

  4. Rafal says:

    I like this without loop an new list if error (int.MinValue) exist

    int someError = (from err in ListTasks
    let CathError = ((Task)err).Result
    where CathError == int.MinValue
    select err

    Like

  5. rafal says:

    I am sorry i was using Count() and i was forgrget write all code .
    int someError = (from err in ListTasks
    let CathError = ((Task)err).Result
    where CathError == int.MinValue
    select err).Count()

    Like

  6. ferrymancoder says:

    Others have pointed this out already, but I’d like to drive the point home:
    _await_ in combination with Task.WhenAll returns an array, so why on earth would you go out of your way to create a list?
    I prefer not to use a specific type to var, so the easy and efficient way to do this would be to declare and assign an array:
    string[] results = await Task.WhenAll(tasks);

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.