What happens to the thread during await in C#? Continuations, ExecutionContext and ASP.NET Core

C# Async & Multithreading November 13, 2026 csharp

While you wait for I/O, no thread is waiting.

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// ======================================================================
// Q: What happens to the thread during await? Where does the code continue?
//
// - While you wait for I/O, no thread is waiting. The operating system (IOCP /
//   epoll) signals when the operation completes.
// - If the Task has already completed (e.g. a cache hit), await continues
//   synchronously, without switching threads.
// - The code before the first await runs synchronously on the caller's thread.
//   An async Task Foo() { HeavyCpu(); await ...; } blocks the caller while
//   HeavyCpu runs.
// - In ASP.NET Core the continuation runs on any thread-pool thread. The
//   ExecutionContext flows with it (AsyncLocal, culture, Activity for tracing).
//   ThreadLocal / [ThreadStatic] do not, so you don't use them in async code.
// ======================================================================

Console.WriteLine(Environment.CurrentManagedThreadId);   // e.g. 12
await httpClient.GetAsync(url, ct);
Console.WriteLine(Environment.CurrentManagedThreadId);   // e.g. 27: different thread, same logical flow