C#
exception handling
Task
asynchronous programming
.NET

What is the best way to catch exception in Task?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Correct exception handling in Task code is essential for reliable .NET applications. Task failures are deferred until you observe completion, so catching errors in the right place matters. This guide covers practical patterns for single tasks, task groups, cancellation, and controlled background work.

Catch at Await Boundaries

For normal async methods, place try and catch around await. This keeps stack traces clear and aligns error flow with async control flow.

csharp
1using System;
2using System.Net.Http;
3using System.Threading.Tasks;
4
5public sealed class WeatherClient
6{
7    private static readonly HttpClient Client = new HttpClient();
8
9    public async Task<string> GetAsync(string url)
10    {
11        try
12        {
13            return await Client.GetStringAsync(url);
14        }
15        catch (HttpRequestException ex)
16        {
17            Console.WriteLine($"Request failed: {ex.Message}");
18            throw;
19        }
20        catch (TaskCanceledException ex)
21        {
22            Console.WriteLine($"Request canceled or timed out: {ex.Message}");
23            throw;
24        }
25    }
26}

Prefer specific exception types and log context like request id or tenant id where available.

Handle Parallel Failures with Task.WhenAll

When several tasks run concurrently, one failure should not hide the rest. Inspect all faulted tasks after WhenAll throws.

csharp
1using System;
2using System.Linq;
3using System.Threading.Tasks;
4
5public static class ImportJob
6{
7    public static async Task RunAsync()
8    {
9        Task[] tasks =
10        [
11            Task.Run(() => throw new InvalidOperationException("Source A corrupted")),
12            Task.Run(() => throw new ArgumentException("Source B format invalid")),
13            Task.Delay(100)
14        ];
15
16        try
17        {
18            await Task.WhenAll(tasks);
19        }
20        catch
21        {
22            foreach (var t in tasks.Where(t => t.IsFaulted && t.Exception != null))
23            {
24                foreach (var ex in t.Exception!.InnerExceptions)
25                {
26                    Console.WriteLine($"Inner failure: {ex.GetType().Name} - {ex.Message}");
27                }
28            }
29            throw;
30        }
31    }
32}

This gives full visibility for diagnostics and postmortem logs.

Distinguish Cancellation from Failure

Cancellation is expected control flow in many systems. Treat it separately from true failures.

csharp
1using System;
2using System.Threading;
3using System.Threading.Tasks;
4
5public static class CancellableWork
6{
7    public static async Task ProcessAsync(CancellationToken token)
8    {
9        for (int i = 0; i < 10; i++)
10        {
11            token.ThrowIfCancellationRequested();
12            await Task.Delay(200, token);
13            Console.WriteLine($"Step {i} complete");
14        }
15    }
16
17    public static async Task RunAsync()
18    {
19        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
20
21        try
22        {
23            await ProcessAsync(cts.Token);
24        }
25        catch (OperationCanceledException)
26        {
27            Console.WriteLine("Operation canceled intentionally");
28        }
29    }
30}

Treating cancellation as failure can produce noisy alerting and false incident reports.

Fire-and-Forget with Explicit Error Capture

Detached tasks should still report exceptions to logs or telemetry.

csharp
1using System;
2using System.Threading.Tasks;
3
4public static class BackgroundStarter
5{
6    public static void Start(Task task, Action<Exception> onError)
7    {
8        _ = task.ContinueWith(
9            t =>
10            {
11                if (t.Exception != null)
12                {
13                    onError(t.Exception.Flatten());
14                }
15            },
16            TaskContinuationOptions.OnlyOnFaulted
17        );
18    }
19}

This avoids silent failures when callers intentionally do not await.

Add Context-Rich Logging

Exception messages alone are rarely enough in distributed systems. Include operation identifiers, user or tenant identifiers, and timing information in logs so failures can be correlated across services. In web apps, attach request correlation ids. In worker services, include job ids and retry counts. Structured logging frameworks make this straightforward and help query failure patterns over time. When rethrowing, prefer preserving the original stack trace rather than creating new wrapper exceptions unless you add meaningful domain context. Good logging reduces the time from incident alert to root-cause confirmation.

Common Pitfalls

A common mistake is using .Result or .Wait() in async flows. This can deadlock UI contexts and wraps errors less readably.

Another issue is swallowing exceptions in broad catch blocks. If the caller must react, rethrow after logging.

Teams also forget to pass cancellation tokens through lower layers. That makes graceful shutdown hard and increases wasted work.

Finally, unobserved exceptions from detached tasks can appear late and without business context. Attach structured logging where tasks are launched.

Summary

  • Catch exceptions at await boundaries for clear async error flow.
  • Inspect all faulted tasks after Task.WhenAll to retain full diagnostics.
  • Treat cancellation as control flow, not always as failure.
  • Track detached tasks with explicit error reporting hooks.
  • Avoid .Result and .Wait() in asynchronous application paths.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.