Asynchronous programming in C# frequently entails doing several tasks at once. Task and Split are two popular approaches to managing many tasks.Task.WhenAll and WaitAll. Despite their apparent similarities, they have different functions and are employed in various contexts. The distinctions between Task.WaitAll and Task.WhenAll are examined in this article, along with real-world examples to show how to use both.


What is Task.WaitAll?
Assignment.The synchronous function WaitAll stops the calling thread after each of the supplied tasks is finished. It's helpful when you have to make sure that a group of tasks is completed before moving on, but it does so in a blocking way, meaning that Task is called by the thread.Until every task is completed, WaitAll is in use.

Example Usage of Task.WaitAll
using System;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {
        Task task1 = Task.Run(() => PerformTask(1));
        Task task2 = Task.Run(() => PerformTask(2));
        Task task3 = Task.Run(() => PerformTask(3));
        Task.WaitAll(task1, task2, task3); // Blocks until all tasks complete
        Console.WriteLine("All tasks completed.");
    }
    static void PerformTask(int taskId)
    {
        Console.WriteLine($"Task {taskId} starting.");
        Task.Delay(1000).Wait(); // Simulate work
        Console.WriteLine($"Task {taskId} completed.");
    }
}


In this example, Task.WaitAll blocks the main thread until all three tasks are complete.

What is Task.WhenAll?

Task.WhenAll is an asynchronous method that returns a single task that is completed when all the provided tasks have been completed. Unlike Task.WaitAll, it does not block the calling thread. Instead, it allows the calling code to continue executing asynchronously.

Example Usage of Task.WhenAll

using System;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
        Task task1 = Task.Run(() => PerformTask(1));
        Task task2 = Task.Run(() => PerformTask(2));
        Task task3 = Task.Run(() => PerformTask(3));
        await Task.WhenAll(task1, task2, task3); // Waits for all tasks to complete asynchronously
        Console.WriteLine("All tasks completed.");
    }
    static void PerformTask(int taskId)
    {
        Console.WriteLine($"Task {taskId} starting.");
        Task.Delay(1000).Wait(); // Simulate work
        Console.WriteLine($"Task {taskId} completed.");
    }
}


In this example, Task.WhenAll allows the main method to await the completion of all tasks without blocking the calling thread.

Key Differences
Blocking vs. Non-blocking

  • Task.WaitAll: Blocks the calling thread until all tasks are complete.
  • Task.WhenAll: Returns a task that can be awaited, allowing the calling thread to continue execution asynchronously.

Return Type

  • Task.WaitAll: Does not return a value.
  • Task.WhenAll: Returns a Task that represents the completion of all provided tasks.

Usage Scenario

  • Task.WaitAll: Used when you need to block until tasks are complete, typically in non-UI or console applications.
  • Task.WhenAll: Used in asynchronous programming, especially in UI applications where blocking the main thread is undesirable.

Practical Use Cases
When to Use Task.WaitAll

  • In console applications where you need to ensure that certain tasks are completed before moving on.
  • When you are dealing with legacy code that doesn’t support async/await patterns.

When to Use Task.WhenAll

  • In UI applications keep the interface responsive.
  • In web applications handle multiple asynchronous operations without blocking the main thread.

Conclusion
Task.WaitAll and Task.WhenAll are essential tools in C# for handling multiple tasks. Use Task.WaitAll when you need to block the calling thread until tasks are complete, and Task.WhenAll for asynchronous waiting. Understanding their differences and appropriate use cases can help you write more efficient and responsive applications.