C# Tutorial · Advanced C# · Lesson 20 of 22

C# Async and Await

Task, async/await, Task.WhenAll and cancellation.

async and await

I/O-bound work — HTTP calls, database queries, file access — should be asynchronous so threads aren't blocked waiting. An async method returns Task or Task<T>; await waits without blocking:

Example 1
using System.Diagnostics;

static async Task<string> FetchAsync(string name, int ms)
{
    await Task.Delay(ms);   // pretend to call an API
    return $"{name} done";
}

var sw = Stopwatch.StartNew();
Console.WriteLine(await FetchAsync("first", 100));
Console.WriteLine(await FetchAsync("second", 100));
Console.WriteLine($"sequential ≈ {Math.Round(sw.ElapsedMilliseconds / 100.0) * 100} ms");

sw.Restart();
string[] results = await Task.WhenAll(FetchAsync("a", 100), FetchAsync("b", 100), FetchAsync("c", 100));
Console.WriteLine($"{string.Join(", ", results)}: parallel ≈ {Math.Round(sw.ElapsedMilliseconds / 100.0) * 100} ms");

using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(50));
try { await Task.Delay(1000, cts.Token); }
catch (TaskCanceledException) { Console.WriteLine("cancelled after timeout"); }

Output

first done
second done
sequential ≈ 200 ms
a done, b done, c done: parallel ≈ 100 ms
cancelled after timeout

Run this on your computer — see “Get Started” for setup.

Rules of thumb

  • Make it async all the way: don't call .Result or .Wait() (deadlocks and blocked threads).
  • Pass a CancellationToken through async calls so work can stop early.
  • Use Task.WhenAll for independent operations.

Test yourself

What does an async method that returns a number have as its return type?

  1. int
  2. Task<int>
  3. async int
  4. Promise<int>
Show answer

Answer: Task<int>