SynchronizationContext & `ConfigureAwait(false)` in Libraries
1Concept
By default, `await` captures the current `SynchronizationContext` (UI thread or ASP.NET Framework context) and marshals the continuation back to that thread. `ConfigureAwait(false)` bypasses context capturing, resuming on any available ThreadPool thread.
2Architecture Diagram
await httpClient.GetAsync(...); (Default) ├── Captures UI SynchronizationContext └── Marshals continuation back to UI Thread (Thread Hop Overhead!) await httpClient.GetAsync(...).ConfigureAwait(false); ├── Ignores SynchronizationContext └── Resumes immediately on ThreadPool thread (High Speed!)
3Code Example
C# 13 & .NET 9
using System;
using System.Threading.Tasks;
public class ConfigureAwaitDemo
{
public static async Task<int> LibraryComputeAsync()
{
// ConfigureAwait(false) in libraries prevents deadlocks and skips context hops
await Task.Delay(10).ConfigureAwait(false);
return 42;
}
public static async Task Main()
{
int result = await LibraryComputeAsync();
Console.WriteLine($"Library Result: {result}");
}
}4Expected Output
Library Result: 42
5Key Takeaways
- ✓Always use `ConfigureAwait(false)` in class libraries and non-UI backend code.
- ✓Modern ASP.NET Core has NO `SynchronizationContext` by design.
- ✓Do not use `ConfigureAwait(false)` in UI event handlers that must touch UI controls directly.