Understanding the Problem
Async deadlocks in .NET are sneaky. They happen when you mix blocking calls like .Result or .Wait() with asynchronous code, and the synchronization context tries to reclaim a thread that’s already stuck waiting. In a web API, this often surfaces as a request that never returns, leaving connections pooled and threads exhausted.
Common Triggers
- Calling
asyncmethods from synchronous event handlers without proper context handling. - Using
ConfigureAwait(false)incorrectly in library code that later needs the context. - Deadlocks between
asyncmethods that lock on shared objects while awaiting.
The first step is instrumenting your application. Tools like PerfView, dotTrace, or the built-in DiagnosticSource events can reveal threads stuck in wait states. Pay attention to threads parked in Task.Wait() or Task.Result calls during request processing.