Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
What is the difference between Task.WhenAll() and Task.WaitAll() in C#?
The Task.WaitAll() and Task.WhenAll() methods in C# serve different purposes when working with multiple asynchronous tasks. Task.WaitAll() blocks the current thread until all tasks complete, while Task.WhenAll() returns a new task that represents the completion of all provided tasks without blocking the calling thread.
Understanding the difference between these methods is crucial for building responsive applications, especially those with user interfaces where blocking the main thread can freeze the UI.
Syntax
Following is the syntax for Task.WaitAll() −
Task.WaitAll(task1, task2, task3);
// or with timeout
Task.WaitAll(new Task[] { task1, task2 }, TimeSpan.FromSeconds(30));
Following is the syntax for Task.WhenAll() −
Task combinedTask = Task.WhenAll(task1, task2, task3); // or with await await Task.WhenAll(task1, task2, task3);
Key Differences
| Task.WaitAll() | Task.WhenAll() |
|---|---|
| Blocks the calling thread | Returns a Task without blocking |
| Synchronous operation | Asynchronous operation |
| Returns void | Returns Task or Task<T[]> |
| Can cause UI freezing | Keeps UI responsive |
Using Task.WaitAll() - Blocking Approach
The Task.WaitAll() method blocks the current thread and waits for all tasks to complete before proceeding −
using System;
using System.Threading.Tasks;
namespace DemoApplication {
public class Program {
static void Main(string[] args) {
Task task1 = Task.Run(() => {
for (int i = 0; i < 3; i++) {
Console.WriteLine($"Task 1 - iteration {i}");
Task.Delay(1000).Wait();
}
Console.WriteLine("Task 1 complete");
});
Task task2 = Task.Run(() => {
Task.Delay(500).Wait();
Console.WriteLine("Task 2 complete");
});
Console.WriteLine("Waiting for tasks to complete...");
Task.WaitAll(task1, task2);
Console.WriteLine("All tasks completed!");
}
}
}
The output of the above code is −
Waiting for tasks to complete... Task 1 - iteration 0 Task 2 complete Task 1 - iteration 1 Task 1 - iteration 2 Task 1 complete All tasks completed!
Using Task.WhenAll() - Non-Blocking Approach
The Task.WhenAll() method returns a task that completes when all provided tasks complete, without blocking the calling thread −
using System;
using System.Threading.Tasks;
namespace DemoApplication {
public class Program {
static async Task Main(string[] args) {
Task task1 = Task.Run(async () => {
for (int i = 0; i < 3; i++) {
Console.WriteLine($"Task 1 - iteration {i}");
await Task.Delay(1000);
}
Console.WriteLine("Task 1 complete");
});
Task task2 = Task.Run(async () => {
await Task.Delay(500);
Console.WriteLine("Task 2 complete");
});
Console.WriteLine("Waiting for tasks to complete...");
await Task.WhenAll(task1, task2);
Console.WriteLine("All tasks completed!");
}
}
}
The output of the above code is −
Waiting for tasks to complete... Task 2 complete Task 1 - iteration 0 Task 1 - iteration 1 Task 1 - iteration 2 Task 1 complete All tasks completed!
Working with Return Values
When tasks return values, Task.WhenAll() can aggregate the results into an array −
using System;
using System.Threading.Tasks;
namespace DemoApplication {
public class Program {
static async Task Main(string[] args) {
Task<int> task1 = Task.Run(async () => {
await Task.Delay(1000);
return 10;
});
Task<int> task2 = Task.Run(async () => {
await Task.Delay(500);
return 20;
});
Task<int> task3 = Task.Run(() => 30);
int[] results = await Task.WhenAll(task1, task2, task3);
Console.WriteLine("Results:");
for (int i = 0; i < results.Length; i++) {
Console.WriteLine($"Task {i + 1} result: {results[i]}");
}
Console.WriteLine($"Sum: {results[0] + results[1] + results[2]}");
}
}
}
The output of the above code is −
Results: Task 1 result: 10 Task 2 result: 20 Task 3 result: 30 Sum: 60
When to Use Each Method
Use Task.WaitAll() when you need to block the current thread and wait synchronously, typically in console applications or non-UI scenarios where blocking is acceptable.
Use Task.WhenAll() in asynchronous methods with await, especially in UI applications, web applications, or any scenario where you want to maintain responsiveness while waiting for multiple tasks to complete.
Conclusion
Task.WaitAll() blocks the calling thread synchronously, while Task.WhenAll() returns an awaitable task without blocking. Use Task.WhenAll() with await in asynchronous methods to maintain application responsiveness, especially in UI applications where thread blocking can freeze the interface.
