Task.WhenAll()
Creates a task that will complete when all of the provided tasks have completed, whether successfully, by faulting, or by being canceled.
Task Task.WhenAll(params Task[] tasks)This static page keeps the syntax and examples indexed for search, while the coding app handles interactive exploration and saved references.
What it does
Overview
Creates a task that will complete when all of the provided tasks have completed, whether successfully, by faulting, or by being canceled.
`Task.WhenAll()` is a powerful method in C# for orchestrating multiple asynchronous operations concurrently. It takes an array or `IEnumerable` of `Task` or `Task<TResult>` objects and returns a single `Task`. This returned task completes only when *all* the input tasks have finished their execution. If all input tasks complete successfully, the `WhenAll` task also completes successfully. If any of the input tasks fault, the `WhenAll` task will also fault, and its `Exception` property will contain an `AggregateException` that wraps all the exceptions from the faulted tasks. If any task is canceled, the `WhenAll` task will also be canceled. This method is crucial for scenarios where you need to perform several independent asynchronous operations in parallel and then wait for all of them to finish before proceeding. For example, fetching data from multiple APIs simultaneously. Time complexity is not directly applicable to `WhenAll` itself, but the overall execution time will be dominated by the longest-running task among the collection. Edge cases include passing an empty collection (returns an already completed task), or a collection containing `null` tasks (throws `ArgumentNullException`). Best practices involve using `WhenAll` to maximize concurrency for independent operations, and always `await`ing the result to properly observe any potential exceptions from the constituent tasks.
Quick reference
Syntax
Task Task.WhenAll(params Task[] tasks)
Inputs
Parameters
See it in practice
Examples
Waiting for multiple void tasks to complete
using System.Threading.Tasks;
using System;
public class WhenAllVoidExample
{
public static async Task DoWork(string name, int delay)
{
Console.WriteLine($"{name} starting...");
await Task.Delay(delay);
Console.WriteLine($"{name} finished.");
}
public static async Task Main()
{
Task task1 = DoWork("Task A", 2000);
Task task2 = DoWork("Task B", 1000);
Task task3 = DoWork("Task C", 1500);
Console.WriteLine("Waiting for all tasks...");
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("All tasks completed.");
}
}Waiting for all tasks... Task A starting... Task B starting... Task C starting... Task B finished. Task C finished. Task A finished. All tasks completed.
Launches three independent tasks and waits for all of them to finish before proceeding.
Waiting for multiple tasks with results
using System.Threading.Tasks;
using System;
using System.Linq;
public class WhenAllResultExample
{
public static async Task<int> GetNumberAsync(int id, int delay)
{
await Task.Delay(delay);
return id * 10;
}
public static async Task Main()
{
Task<int> num1 = GetNumberAsync(1, 1000);
Task<int> num2 = GetNumberAsync(2, 500);
Task<int> num3 = GetNumberAsync(3, 1200);
int[] results = await Task.WhenAll(num1, num2, num3);
Console.WriteLine($"Results: {string.Join(", ", results)}");
Console.WriteLine($"Sum: {results.Sum()}");
}
}Results: 10, 20, 30 Sum: 60
Collects results from multiple `Task<T>` objects after all have completed, returning an array of `T`.
Handling exceptions from WhenAll
using System.Threading.Tasks;
using System;
public class WhenAllErrorExample
{
public static async Task FailTask(string name, int delay, bool shouldFail)
{
await Task.Delay(delay);
if (shouldFail) throw new Exception($"{name} failed!");
Console.WriteLine($"{name} succeeded.");
}
public static async Task Main()
{
Task t1 = FailTask("Task X", 500, false);
Task t2 = FailTask("Task Y", 1000, true);
Task t3 = FailTask("Task Z", 700, false);
try
{
await Task.WhenAll(t1, t2, t3);
}
catch (AggregateException ae)
{
foreach (var ex in ae.InnerExceptions)
{
Console.WriteLine($"Caught exception: {ex.Message}");
}
}
}
}Task X succeeded. Task Z succeeded. Caught exception: Task Y failed!
`WhenAll` wraps exceptions from multiple faulted tasks into an `AggregateException`.
Debug faster
Common Errors
Logical Error
Cause: Not `await`ing the `Task.WhenAll` result, which can lead to unobserved exceptions if any of the constituent tasks fail.
Fix: Always `await` the `Task.WhenAll` call within a `try-catch` block to properly handle any `AggregateException` that might occur.
Task t1 = Task.Run(() => { throw new Exception("Error!"); });
Task.WhenAll(t1); // Exception might go unobserved if not awaitedRuntime support
Compatibility
Source: Microsoft Learn
Common questions
Frequently Asked Questions
Creates a task that will complete when all of the provided tasks have completed, whether successfully, by faulting, or by being canceled.
tasks: The tasks to wait for.
Logical Error: Always `await` the `Task.WhenAll` call within a `try-catch` block to properly handle any `AggregateException` that might occur.