8 async/await mistakes that crash your C# applications (and how to fix them)
Many production crashes come from a single source: misused async/await. And it can rot any C# app.
We've all been there: joining a project and discovering that async is badly implemented. Production deadlocks, swallowed exceptions, unpredictable behavior... Here are 8 mistakes that turn your C# code into a bug generator.
1. Not awaiting an async method
The method starts but your code moves on without waiting. Exceptions are swallowed and the result is ignored.
// ❌ SomeAsyncMethod();
// ✅ await SomeAsyncMethod();
2. Using async void instead of async Task
These methods can't be awaited, exceptions surface differently and cause crashes.
// ❌ async void MyMethod()
// ✅ async Task MyMethod()
3. Blocking with .Result or .Wait()
High deadlock risk, especially in UI and ASP.NET applications.
// ❌ var result = SomeAsyncMethod().Result;
// ✅ var result = await SomeAsyncMethod();
4. Ignoring the synchronization context
Useless hops back to the main thread (especially in non-UI code) hurt performance.
// ❌ await SomeLongRunningMethodAsync();
// ✅ await SomeLongRunningMethodAsync().ConfigureAwait(false);
5. Mishandling async exceptions
Lost debugging information and unpredictable behavior. A bare try/catch without proper propagation isn't enough: capture AND propagate exceptions.
6. Overusing async for synchronous operations
Useless overhead that degrades application performance.
// ❌ async Task<int> AddAsync(int a, int b) { return await Task.FromResult(a + b); }
// ✅ int Add(int a, int b) { return a + b; }
7. Using Task.Run for I/O work
Wasting threads on operations that are already non-blocking by nature.
// ❌ await Task.Run(() => SomeIOMethod());
// ✅ await SomeIOMethodAsync();
8. Forgetting to return a Task
Calling code can't know when the operation finished, nor handle its errors.
// ❌ async void DoSomethingAsync() { SomeOtherAsyncMethod(); }
// ✅ async Task DoSomethingAsync() { await SomeOtherAsyncMethod(); }
Takeaway: each of these mistakes may look minor, yet any of them can crash your app in production. Avoiding them isn't just cleaner code: it protects your business and your sanity.
This article comes from one of my LinkedIn posts (in French): join the discussion ↗