<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. C#
  3. Advanced C#
All lessons in this course

Lesson 48 of 60 16 minAdvanced

async and await

Keep apps responsive while waiting for files, networks and databases: Task, async methods, await, running waits together, cancellation and the classic mistakes.

Downloading a model, reading a big file or querying a database involves waiting, often for seconds. If the UI thread waits, the window freezes. async and await let a method pause while it waits without blocking the thread, and continue when the result arrives.

Interactive

Blocking vs async

Download.cs
async Task LoadAllAsync(){    var a = await client.GetStringAsync(urlA);    var b = await client.GetStringAsync(urlB);    var c = await client.GetStringAsync(urlC);}
My BIM App
clicks handled: 0
steel.ifc
drawings.pdf
report.csv
t = 0.0 s / 3.0 s
await frees the UI thread while waiting for the network, so the app stays responsive. The downloads still happen one after another, so the total time is the sum.

Task and Task<T>

A Task represents work that will finish in the future. Task<T> will also produce a value of type T. Asynchronous .NET methods return tasks and are named with the suffix Async: File.ReadAllTextAsync, HttpClient.GetStringAsync.

Writing an async method

LoadModel.cs
public async Task<int> CountMembersAsync(string path){    string json = await File.ReadAllTextAsync(path);   // thread is free while the disk works    var model = JsonSerializer.Deserialize<Model>(json)!;    return model.Members.Count;                       // wrapped in Task<int> automatically} // caller (in a WPF button handler)private async void LoadButton_Click(object sender, RoutedEventArgs e){    StatusText.Text = "Loading…";    int n = await CountMembersAsync("tower.json");    StatusText.Text = $"{n} members";                  // back on the UI thread}
  • Mark the method async; return Task, Task<T> (or ValueTask).
  • await pauses this method until the task completes; the thread goes off to do other work (like repainting the UI).
  • After the await, code continues, on the UI thread in desktop apps, so you can update controls.
  • async void is only for event handlers. Everywhere else return Task, so callers can await and catch errors.

Waiting for several things together

WhenAll.cs
var http = new HttpClient(); Task<string> a = http.GetStringAsync("https://example.com/a");Task<string> b = http.GetStringAsync("https://example.com/b");   // both requests in flight string[] results = await Task.WhenAll(a, b);       // total ≈ the slower oneConsole.WriteLine(results[0].Length + results[1].Length); Task<string> first = await Task.WhenAny(a, b);     // whichever finishes first

Cancellation

Cancel.cs
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));   // auto-cancel after 10 sCancelButton.Click += (_, _) => cts.Cancel(); try{    await ExportAsync("tower.ifc", cts.Token);}catch (OperationCanceledException){    StatusText.Text = "Export cancelled";} async Task ExportAsync(string path, CancellationToken token){    foreach (var member in members)    {        token.ThrowIfCancellationRequested();           // check regularly        await WriteMemberAsync(member, token);         // pass the token down    }}

Classic mistakes

MistakeWhy it hurtsInstead
task.Result or task.Wait()blocks the thread; can deadlock in UI appsawait task
async void methodsexceptions can’t be caught by the caller and can crash the appreturn Task
forgetting awaitthe method continues before the work is done; errors are lostalways await (or store and await later)
await in a loop for independent workruns one by onestart all, then Task.WhenAll
Task.Run around I/O methodswastes a thread just to waitawait the real …Async method
Quick check

What does await do while the awaited task is still running?

Quick check

Three independent downloads take 1 s each. Roughly how long does await Task.WhenAll(a, b, c) take if all three were started first?

Practice

Write static async Task<long> TotalSizeAsync(string[] paths) that reads all files concurrently with File.ReadAllBytesAsync and returns the total number of bytes. Print the result for two files.

Show the solution
Solution.cs
static async Task<long> TotalSizeAsync(string[] paths){    Task<byte[]>[] reads = paths.Select(p => File.ReadAllBytesAsync(p)).ToArray();    byte[][] contents = await Task.WhenAll(reads);    return contents.Sum(c => (long)c.Length);} long total = await TotalSizeAsync(new[] { "a.ifc", "b.ifc" });Console.WriteLine($"{total:N0} bytes");
Output
4,812,330 bytes

Remember

  • async methods return Task/Task<T> and use await to wait without blocking.
  • Await I/O to keep UIs responsive and servers scalable.
  • Start independent work first, then await Task.WhenAll(...).
  • Avoid .Result, .Wait() and async void (except event handlers); support cancellation.
0 of 60 lessons completed