Skip to content

C# async void Method Error Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about C# async void Method Error Fix. We cover key concepts, practical examples, and best practices.

A button click handler calls an async method but the app crashes silently or exceptions disappear into the void:

private async void Button_Click(object sender, EventArgs e)
{
    await LoadDataAsync();
}

async void methods cannot be awaited by the caller and any unhandled exception escapes to the SynchronizationContext, which typically crashes the entire process. Never use async void except for event handlers.

Step-by-Step Fix

1. Replace async void with async Task

WRONG — fire-and-forget with no way to catch errors:

public async void ProcessOrder(Order order)
{
    await SaveAsync(order);
}

RIGHT — return Task so callers can await and catch:

public async Task ProcessOrderAsync(Order order)
{
    await SaveAsync(order);
}

Now callers can properly await:

await ProcessOrderAsync(order);

2. Handle event handlers properly

When you must use async void (UI event handlers), wrap the body in try-catch:

WRONG — uncaught exception crashes the app:

private async void SaveButton_Click(object sender, EventArgs e)
{
    await SaveToDatabaseAsync();
}

RIGHT — catch and handle the error:

private async void SaveButton_Click(object sender, EventArgs e)
{
    try
    {
        await SaveToDatabaseAsync();
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Save failed: {ex.Message}");
    }
}

Expected output: a message box appears instead of a crash.

3. Pass errors back to the caller

WRONG — swallowing exceptions in async void:

public async void StartProcessing()
{
    await Task.Run(() => throw new InvalidOperationException());
}

RIGHT — use async Task and let the caller decide:

public async Task StartProcessingAsync()
{
    await Task.Run(() => throw new InvalidOperationException());
}

Callers handle it:

try
{
    await StartProcessingAsync();
}
catch (InvalidOperationException ex)
{
    Logger.Log(ex);
}

4. Fire-and-forget with logging

When you genuinely need fire-and-forget (like logging), use Task.Run with explicit error handling:

WRONG — async void fire-and-forget:

public async void LogMessage(string msg)
{
    await File.AppendAllTextAsync("log.txt", msg);
}

RIGHT — use a dedicated fire-and-forget helper:

public void FireAndForget(Func<Task> task)
{
    Task.Run(async () =>
    {
        try
        {
            await task();
        }
        catch (Exception ex)
        {
            Logger.Log(ex);
        }
    });
}

Usage:

FireAndForget(() => LogMessageAsync("started"));

Prevention

  • Use async Task instead of async void for every method except event handlers.
  • Keep event handler async void methods minimal — delegate to async Task methods.
  • Always wrap async void event handler bodies in try-catch.
  • Enable CA2007 warning in your .editorconfig to catch async void patterns.
  • Use await Task.ConfigureAwait(false) in library code to avoid deadlocks.

Common Mistakes with async void

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Why does async void crash my app on exception?

async void methods cannot be awaited, so the exception has no caller to propagate to. It escapes to the SynchronizationContext, which in most application models (ASP.NET, WPF, WinForms) triggers an unhandled exception that crashes the process.

Can I unit test an async void method?

No. Because async void returns void (not Task), the test framework cannot await it. The test completes before the async work finishes. Always return Task for testability.

Is async void ever the right choice?

Only for event handlers in UI frameworks (WPF, WinForms, Xamarin, Blazor) where the delegate signature requires void. In every other case, use async Task.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro