█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/C# and .NET/Async/Await in C#
55 minIntermediate

Async/Await in C#

After this lesson, you will be able to: Use the Task-based async pattern (async/await) with ConfigureAwait and cancellation tokens.

Async/await in C# is the model TypeScript and Python copied. Once you've used it in C# you'll wonder how anyone writes blocking code.

Prerequisites:LINQ

async/await basics

Mark a method `async`; return Task or Task<T>; await any other async call.

tsx
using System.Net.Http;
using System.Threading.Tasks;
static async Task<string> FetchUserAsync(int id) {
using var http = new HttpClient();
var response = await http.GetAsync($"https://api.example.com/users/{id}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
// Calling async from sync
var user = await FetchUserAsync(1); // only valid in async context
// Top-level await works in .NET 6+
// In libraries / older code, you might see .Result or .Wait(), AVOID, they deadlock in some contexts

Parallel awaits

Multiple in-flight requests with Task.WhenAll.

tsx
// Sequential, slow
var u1 = await FetchUserAsync(1);
var u2 = await FetchUserAsync(2);
var u3 = await FetchUserAsync(3);
// Parallel, fast
var tasks = new[] { FetchUserAsync(1), FetchUserAsync(2), FetchUserAsync(3) };
string[] users = await Task.WhenAll(tasks);
// First-to-complete
string fastest = await Task.WhenAny(tasks).Unwrap();

Cancellation tokens

Standard pattern for cancellable async ops.

tsx
using System.Threading;
static async Task<string> FetchWithTimeoutAsync(
int id,
CancellationToken cancellationToken = default
) {
using var http = new HttpClient();
var response = await http.GetAsync(
$"https://api.example.com/users/{id}",
cancellationToken); // propagate the token to the underlying call
return await response.Content.ReadAsStringAsync(cancellationToken);
}
// Caller cancels after 5 seconds
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
try {
var user = await FetchWithTimeoutAsync(1, cts.Token);
} catch (OperationCanceledException) {
Console.WriteLine("timed out");
}

ConfigureAwait + sync contexts

Library code should ConfigureAwait(false) to avoid deadlocks.

tsx
// In a library:
var data = await http.GetStringAsync(url).ConfigureAwait(false);
// Why? Without ConfigureAwait(false), after await, execution resumes on the original
// 'sync context' (UI thread in WPF/WinForms; HttpContext in old ASP.NET).
// In a library called from such a context, this can deadlock or serialize work.
// ConfigureAwait(false) says 'I don't need the original context.'
//
// In ASP.NET Core, there's no sync context, so ConfigureAwait(false) is a no-op.
// In modern app code, you can usually skip it. In library code, always use it.

💡 async all the way down

If a method calls async, it should BE async. Don't call .Result / .Wait() / .GetAwaiter().GetResult(), they block a thread + can deadlock. Top of the call stack is the only legitimate sync point (Main in console, framework entry in ASP.NET). Use `async void` only for event handlers, anywhere else makes exceptions unobservable.

Common mistakes

Calling `.Result` or `.Wait()` on a Task (deadlock + perf loss). Not propagating CancellationToken into nested calls. `async void` outside of event handlers, exceptions silently crash the process. Awaiting in a loop when Task.WhenAll would parallelize.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←Collections and LINQ
Back to C# and .NET
ASP.NET Core REST APIs→