C# Academy · Lesson

ConfigureAwait, exception flow

Understand context capture and ConfigureAwait(false); handle exceptions with await vs blocking; see AggregateException and best practices.

Lesson 3 of 38 steps

ConfigureAwait, exception flow is a free C# Academy lesson on CoddyKit. This is lesson 3 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 3 lessons in total.

Context & exceptions

Goals:

  • Know what context capture is
  • When to use ConfigureAwait(false)
  • How exceptions flow with await
  • Why blocking leads to AggregateException

Library best practice

Library methods should use ConfigureAwait(false) to avoid resuming on a UI/web context they do not own.

using System;
using System.Threading.Tasks;

public static class NetLib
{
  // Library code should not assume a UI context. Use ConfigureAwait(false).
  public static async Task<string> FetchAsync()
  {
    await Task.Delay(100).ConfigureAwait(false); // do not capture context
    return "payload";
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    // Console apps typically have no SynchronizationContext; this still runs fine.
    string s = NetLib.FetchAsync().GetAwaiter().GetResult();
    Console.WriteLine("Got: " + s);
  }
}

Context rules

Context capture:

  • Default await tries to resume on the captured context (UI/ASP.NET)
  • ConfigureAwait(false) says: do not capture; resume on the thread pool
  • Helps avoid deadlocks when callers block the context thread
  • UI code may need the context to update controls; library code usually should not

Await and exceptions

When you await, the exception flows as the original exception type; catch it normally.

using System;
using System.Threading.Tasks;

public class Program
{
  static async Task<string> BoomAsync()
  {
    await Task.Delay(50);
    throw new InvalidOperationException("boom");
  }

  public static void Main(string[] args)
  {
    // With await (inside async), exceptions rethrow as the original type.
    try
    {
      string r = BoomAsync().GetAwaiter().GetResult(); // emulate await in Main
      Console.WriteLine(r);
    }
    catch (InvalidOperationException ex)
    {
      Console.WriteLine("Caught: " + ex.GetType().Name + " - " + ex.Message);
    }
  }
}

Blocking and errors

Blocking with .Result or .Wait() wraps errors into AggregateException; prefer await for clearer error flow.

using System;
using System.Threading.Tasks;

public class Program
{
  static async Task<int> FailsAsync()
  {
    await Task.Delay(30);
    throw new ArgumentException("bad arg");
  }

  public static void Main(string[] args)
  {
    try
    {
      // Blocking with .Result wraps the exception into AggregateException
      int x = FailsAsync().Result;
      Console.WriteLine(x);
    }
    catch (AggregateException ae)
    {
      Exception inner = ae.InnerException;
      Console.WriteLine("AggregateException -> " + (inner == null ? "null" : inner.GetType().Name));
    }
  }
}

Best practices

Guidelines:

  • In libraries: use ConfigureAwait(false)
  • In UI/web: await on the calling thread when you need the context
  • Avoid .Result/.Wait(); catch original exceptions with await
  • Log and rethrow with context-aware messages if needed

ConfigureAwait behavior

Quick check: What does ConfigureAwait(false) tell an await to do?

Recap

Recap: Use ConfigureAwait(false) in libraries; let UI/web code decide when it needs the context. Prefer await for clear exception flow; blocking wraps errors and risks deadlocks.

Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “ConfigureAwait, exception flow” lesson free?

Yes — the full text of “ConfigureAwait, exception flow” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 3 lessons in total.

What will I learn in “ConfigureAwait, exception flow”?

Understand context capture and ConfigureAwait(false); handle exceptions with await vs blocking; see AggregateException and best practices. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 3.

How long does the “ConfigureAwait, exception flow” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Task/ValueTask and the async state machine (concepts)
  2. Async pitfalls: sync-over-async and deadlocks
  3. ConfigureAwait, exception flow
← Back to C# Academy