async/await in .NET compiles to a state machine that resumes on a captured SynchronizationContext or ThreadPool. ConfigureAwaitOptions (enum in .NET 8) replaces .ConfigureAwait(false). .NET 9's Task.WhenEach streams results as tasks complete. Channel<T> and SemaphoreSlim implement bounded concurrency. Understanding context capture, deadlocks, and CancellationToken propagation separates reliable async code from the fragile kind.
WhenAll fan-out vs WhenEach streaming vs Channel bounded concurrency.
Calling .Result or .Wait() on a Task in an async context will deadlock when a SynchronizationContext is present.
Task.WhenEach (.NET 9) lets you process results as tasks complete. Ideal for showing partial results in a loop.
ValueTask is an optimisation for methods that are frequently synchronous (cache hit). Do not use by default — only measure then apply.
Sign in to share your feedback and join the discussion.