← ClaudeAtlas

async-await-pitfallslisted

Review C# async/await code for deadlocks, sync-over-async, async void, ValueTask misuse, fire-and-forget, and CancellationToken propagation. Use when writing or reviewing any async C# code.
Sarmkadan/dotnet-senior-skills · ★ 0 · AI & Automation · score 72
Install: claude install-skill Sarmkadan/dotnet-senior-skills
# Async/Await Pitfalls ## Sync-over-async `.Result`, `.Wait()`, `.GetAwaiter().GetResult()` on an incomplete task: instant rejection in request paths. In classic ASP.NET, WPF, WinForms it deadlocks (continuation needs the captured context the blocking thread holds). In ASP.NET Core it does not deadlock but burns a thread-pool thread per call and collapses under load via pool starvation - the symptom is p99 latency spiking while CPU is idle. ```csharp // WRONG var user = _client.GetUserAsync(id).Result; // RIGHT: make the caller async all the way up to the controller/handler var user = await _client.GetUserAsync(id); ``` There is no safe wrapper. `Task.Run(...).Result` avoids the deadlock, costs two threads, and hides the design error. Fix the call chain. Acceptable exceptions: `Main` before async Main existed, and `IDisposable.Dispose` bridging (prefer `IAsyncDisposable`). ## ConfigureAwait - Library code (no ASP.NET Core dependency, may be consumed from UI or legacy contexts): `ConfigureAwait(false)` on every await. One missing await re-introduces the deadlock risk for UI callers. - ASP.NET Core application code: there is no SynchronizationContext; `ConfigureAwait(false)` is noise. Do not demand it in app-level reviews. ## async void Only for event handlers. Anywhere else, exceptions escape to the SynchronizationContext or crash the process, the caller cannot await or observe completion, and tests pass while work is still running. ```csharp // WRONG public async voi