async, await, Task & CancellationToken Masterclass
Welcome to Phase 10 (Chapter 28): C# async, await, Task<T>, CancellationToken & Parallel Async Masterclass! Asynchronous programming enables applications to remain responsive while waiting for slow I/O operations (database queries, HTTP calls, file reads). In this lesson, we master Task, Task<T>, async methods, await, exception handling in async, CancellationToken, and parallel async patterns (Task.WhenAll, Task.WhenAny).
// Async method returning Task
static async Task<string> GetMessageAsync()
{
// await releases the calling thread while Task.Delay runs (simulates I/O)
await Task.Delay(1000);
return "Data received successfully!";
}
// Main async entry point (C# 7.1+)
string message = await GetMessageAsync();
Console.WriteLine(message);
// CancellationToken โ Cooperative cancellation mechanism
CancellationTokenSource cts = new CancellationTokenSource(timeout: TimeSpan.FromSeconds(3));
static async Task LongOperationAsync(CancellationToken token)
{
for (int i = 1; i <= 10; i++)
{
token.ThrowIfCancellationRequested(); // Exits cleanly if cancelled
Console.WriteLine($"Processing step {i}...");
await Task.Delay(500, token);
}
}
try
{
await LongOperationAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation was cancelled gracefully.");
}
// Task.WhenAll โ Run multiple async tasks in PARALLEL
static async Task Main()
{
Task<string> task1 = FetchDataAsync("API-1");
Task<string> task2 = FetchDataAsync("API-2");
Task<string> task3 = FetchDataAsync("API-3");
string[] results = await Task.WhenAll(task1, task2, task3);
Console.WriteLine($"All results received: {results.Length}");
}
Q1: What happens if I don't await an async method?
If you call an async method without await, the returned Task fires and is discarded. Exceptions thrown inside that Task will be unobserved and silently swallowed (or crash the app in some environments).
Q2: What is the difference between Task.WhenAll and Task.WhenAny?
Task.WhenAll completes when ALL provided tasks finish. Task.WhenAny completes as soon as the FIRST task finishes (useful for timeout patterns and cancellation).
Q3: Should I use async/await everywhere?
Use async/await for I/O-bound operations (database, file, network). For CPU-bound heavy computation, use Task.Run() to offload to a background thread pool thread.