DEV Community

Cover image for Mastering Task.WhenAll in .NET: Run Tasks Concurrently Like a Pro
Morteza Jangjoo
Morteza Jangjoo

Posted on

Mastering Task.WhenAll in .NET: Run Tasks Concurrently Like a Pro

As .NET developers, we often deal with scenarios where multiple asynchronous operations need to run — fetching data from APIs, reading files, calling services, or performing database queries. A common question arises: Should we await tasks one by one, or can we run them all at once?

That’s where Task.WhenAll comes into play.


1. Running Tasks Sequentially

public async Task SequentialExampleAsync()
{
    var result1 = await GetDataFromApiAsync("https://api.service1.com/data");
    var result2 = await GetDataFromApiAsync("https://api.service2.com/data");
    var result3 = await GetDataFromApiAsync("https://api.service3.com/data");

    Console.WriteLine($"{result1}, {result2}, {result3}");
}
Enter fullscreen mode Exit fullscreen mode

Pros

  • Easy to read and understand.
  • Errors are caught immediately.

Cons

  • Each task starts only after the previous finishes.
  • If each takes 1 second, total time = 3 seconds.

2. Running Tasks Concurrently with Task.WhenAll

public async Task ParallelExampleAsync()
{
    var task1 = GetDataFromApiAsync("https://api.service1.com/data");
    var task2 = GetDataFromApiAsync("https://api.service2.com/data");
    var task3 = GetDataFromApiAsync("https://api.service3.com/data");

    var results = await Task.WhenAll(task1, task2, task3);

    Console.WriteLine($"{results[0]}, {results[1]}, {results[2]}");
}
Enter fullscreen mode Exit fullscreen mode

Pros

  • Tasks run in parallel.
  • If each takes 1 second, total time ≈ 1 second.

Cons

  • If one fails, Task.WhenAll throws an exception.

3. Error Handling

try
{
    var task1 = GetDataFromApiAsync("https://api.invalid.com");
    var task2 = GetDataFromApiAsync("https://api.service2.com/data");

    await Task.WhenAll(task1, task2);
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
Enter fullscreen mode Exit fullscreen mode

When multiple tasks fail, exceptions are aggregated into an AggregateException.


4. Performance Comparison

Simulation code:

public async Task<string> GetDataFromApiAsync(string url)
{
    await Task.Delay(1000); // Simulate work
    return $"Data from {url}";
}
Enter fullscreen mode Exit fullscreen mode
  • Sequential (await) → ~3 seconds
  • Concurrent (Task.WhenAll) → ~1 second

5. When to Use

  • Sequential: when tasks depend on each other.
  • Task.WhenAll: when tasks are independent and performance matters.

Conclusion

Task.WhenAll is a powerful tool for running independent async operations concurrently in .NET. It can drastically reduce execution time compared to sequential execution.

Next time you fetch data from multiple APIs, don’t line them up one by one — let them run together with Task.WhenAll.


What about you? Do you prefer Task.WhenAll or do you often go with sequential awaits for clarity? Share your experience in the comments!

Get source code from github

I’m Morteza Jangjoo and “Explaining things I wish someone had explained to me”

Top comments (1)

Collapse
 
amarantess profile image
Gabriel Amarantes

Thanks for sharing!