How does async/await work under the hood in C#? What is the state machine?
cs-mid-001
Your answer
Answer as you would in a real interview — explain your thinking, not just the conclusion.
Model answer
The C# compiler rewrites every async method into a struct-based state machine. Each await point becomes a numbered state transition: when the awaited task completes, the runtime resumes the machine from the correct state without blocking a thread. The SynchronizationContext — or the thread pool for ConfigureAwait(false) — decides which thread runs the continuation. This is why async I/O-bound work scales so well on ASP.NET Core: the thread returns to the pool during the wait, so thousands of concurrent requests can share a small thread pool. CPU-bound work still occupies a thread; for that you push to Task.Run.
Code example
// Simple async method
public async Task<string> FetchAsync(string url)
{
// Thread returns to pool here while awaiting I/O
var response = await _httpClient.GetAsync(url).ConfigureAwait(false);
// Resumed on a pool thread when response arrives
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
// Compiler generates roughly:
// private struct FetchAsyncStateMachine : IAsyncStateMachine
// { int _state; ... void MoveNext() { switch (_state) { case 0: ... } } }
Follow-up
What is the difference between Task.Run and async/await? When should you use ConfigureAwait(false), and why is it the default in library code?