How to Use Task.WhenAll in C# for Parallel Task Execution
Use
Task.WhenAll in C# to run multiple asynchronous tasks in parallel and wait until all of them finish. It takes an array or collection of Task objects and returns a single task that completes when all input tasks complete.Syntax
The Task.WhenAll method accepts multiple Task instances and returns a single Task that completes when all provided tasks complete.
Basic syntax:
Task.WhenAll(Task[] tasks)- waits for all tasks to finish.Task.WhenAll<TResult>(Task<TResult>[] tasks)- waits for all tasks and returns an array of results.
csharp
Task WhenAll(Task[] tasks); Task<TResult[]> WhenAll<TResult>(Task<TResult>[] tasks);
Example
This example shows how to start three tasks that complete after different delays, then wait for all of them to finish using Task.WhenAll. It prints the results after all tasks complete.
csharp
using System; using System.Threading.Tasks; class Program { static async Task Main() { Task<int> task1 = Task.Delay(1000).ContinueWith(_ => 1); Task<int> task2 = Task.Delay(2000).ContinueWith(_ => 2); Task<int> task3 = Task.Delay(1500).ContinueWith(_ => 3); int[] results = await Task.WhenAll(task1, task2, task3); Console.WriteLine($"Results: {string.Join(", ", results)}"); } }
Output
Results: 1, 2, 3
Common Pitfalls
Common mistakes when using Task.WhenAll include:
- Not awaiting the returned task, which can cause the program to continue before tasks finish.
- Passing tasks that throw exceptions without handling them, causing
WhenAllto throw anAggregateException. - Using
Task.WaitAll(blocking) instead ofawait Task.WhenAll(async), which can cause deadlocks in UI or async contexts.
csharp
/* Wrong: Not awaiting Task.WhenAll */ Task task1 = Task.Delay(1000); Task task2 = Task.Delay(500); Task.WhenAll(task1, task2); // Missing await - tasks may not complete before program ends /* Right: Await Task.WhenAll */ await Task.WhenAll(task1, task2);
Quick Reference
Summary tips for using Task.WhenAll:
- Use
await Task.WhenAll(tasks)to asynchronously wait for all tasks. - Handle exceptions with try-catch around
await Task.WhenAll. - Use the generic version to get results from multiple tasks.
- Do not block with
.Wait()or.Resultto avoid deadlocks.
Key Takeaways
Use Task.WhenAll to run and wait for multiple tasks in parallel efficiently.
Always await Task.WhenAll to ensure all tasks complete before continuing.
Handle exceptions from Task.WhenAll using try-catch to catch AggregateException.
Use the generic Task.WhenAll to get results from multiple asynchronous operations.
Avoid blocking calls like .Wait() or .Result to prevent deadlocks in async code.