Explain the difference between `Task.WhenAll()` and `Task.WhenAny()`
4 minintermediate.NETasync-awaitTaskconcurrency
Quick Answer
Task.WhenAll() returns a task that completes when all supplied tasks finish (aggregating results and exceptions), so it's used to run independent operations concurrently and wait for every one. Task.WhenAny() completes as soon as any one task finishes, returning that task — useful for timeouts, first-response-wins, or redundancy. Both are non-blocking and awaitable.
Detailed Answer
Task.WhenAll() waits for all tasks in a collection to complete before continuing. It returns a task that completes when all input tasks have completed.
Key characteristics of Task.WhenAll():
- Waits for ALL tasks to finish
- Returns an array of results (if tasks return values)
- If any task throws an exception, the returned task will be faulted
- All exceptions are aggregated in an AggregateException
- Useful for parallel execution where you need all results
// Example: Download multiple files concurrently
var task1 = DownloadFileAsync("file1.txt");
var task2 = DownloadFileAsync("file2.txt");
var task3 = DownloadFileAsync("file3.txt");
// Wait for all downloads to complete
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("All files downloaded");
Task.WhenAny() returns as soon as ANY one of the tasks completes. It returns a task that represents the first completed task.
Key characteristics of Task.WhenAny():
- Returns when the FIRST task completes
- Returns the completed task itself (not the result)
- Useful for timeout scenarios or racing multiple operations
- Other tasks continue running in the background
// Example: Implement timeout pattern
var dataTask = FetchDataAsync();
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5));
var completedTask = await Task.WhenAny(dataTask, timeoutTask);
if (completedTask == timeoutTask)
{
throw new TimeoutException("Operation timed out");
}
var result = await dataTask;