0
0
CsharpDebug / FixBeginner · 4 min read

How to Handle Exceptions in Async C# Correctly

In C#, handle exceptions in async methods by using try-catch blocks around await calls. This ensures exceptions thrown inside async tasks are caught properly and do not crash your program.
🔍

Why This Happens

When you call an async method without await or without proper try-catch, exceptions inside the async task are not caught where you expect. This causes unhandled exceptions or crashes because the error happens on a different thread context.

csharp
using System;
using System.Threading.Tasks;

class Program
{
    static async Task ThrowExceptionAsync()
    {
        await Task.Delay(100);
        throw new InvalidOperationException("Something went wrong!");
    }

    static void Main()
    {
        try
        {
            // Calling async method without await
            ThrowExceptionAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Caught exception: {ex.Message}");
        }

        Console.WriteLine("Main method finished.");
        Console.ReadLine();
    }
}
Output
Main method finished. Unhandled exception. System.InvalidOperationException: Something went wrong! at Program.ThrowExceptionAsync()
🔧

The Fix

Use await when calling async methods inside a try-catch block. This makes sure exceptions thrown inside the async method are caught in the catch block, preventing crashes and allowing graceful error handling.

csharp
using System;
using System.Threading.Tasks;

class Program
{
    static async Task ThrowExceptionAsync()
    {
        await Task.Delay(100);
        throw new InvalidOperationException("Something went wrong!");
    }

    static async Task Main()
    {
        try
        {
            await ThrowExceptionAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Caught exception: {ex.Message}");
        }

        Console.WriteLine("Main method finished.");
    }
}
Output
Caught exception: Something went wrong! Main method finished.
🛡️

Prevention

Always await async methods to catch exceptions properly. Use try-catch blocks around await calls to handle errors gracefully. Avoid calling async methods without await unless you explicitly handle the returned Task. Consider using tools like analyzers or linters that warn about unawaited tasks to prevent silent failures.

⚠️

Related Errors

Common related errors include:

  • UnobservedTaskException: Happens when a faulted task is not awaited or observed.
  • Deadlocks: Blocking on async code with .Result or .Wait() can cause deadlocks.
  • Swallowed exceptions: Forgetting to await tasks can hide exceptions.

Key Takeaways

Always use await when calling async methods to catch exceptions correctly.
Wrap await calls in try-catch blocks to handle errors gracefully.
Avoid calling async methods without await unless you handle the Task explicitly.
Use async Main method in console apps to simplify async exception handling.
Be aware of unobserved task exceptions and deadlocks caused by blocking calls.