gotchacsharpdotnetCritical
async/await: async void causes unhandled exceptions that crash the process
Viewed 0 times
async void exceptionfire and forgetasync void crashunobserved task exceptionasync event handler
Error Messages
Problem
Methods declared async void fire-and-forget. Any exception thrown inside them propagates to the synchronization context and typically crashes the application or is silently swallowed — it cannot be caught at the call site.
Solution
Always return Task or Task<T> from async methods. Use async void only for event handlers where the signature is forced:
// BAD
public async void LoadData() // exception escapes, can't be awaited
{
await FetchAsync();
}
// GOOD
public async Task LoadDataAsync()
{
await FetchAsync();
}
// Event handler — only acceptable async void use
private async void Button_Click(object sender, EventArgs e)
{
try { await LoadDataAsync(); }
catch (Exception ex) { ShowError(ex); } // must catch explicitly
}Why
async void methods cannot be awaited by callers, so exceptions propagate through whatever SynchronizationContext was active when the method started. In ASP.NET Core (no SynchronizationContext) this triggers TaskScheduler.UnobservedTaskException and may crash the process.
Gotchas
- async void in Blazor event callbacks is acceptable because Blazor handles exceptions from them
- Unit testing async void methods is nearly impossible — tests complete before the async work finishes
- Fire-and-forget patterns should use Task.Run or background services, not async void
Revisions (0)
No revisions yet.