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}");
}
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]}");
}
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}");
}
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}";
}
-
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!
I’m Morteza Jangjoo and “Explaining things I wish someone had explained to me”
Top comments (1)
Thanks for sharing!