ConfigureAwait
ConfigureAwait(false)avoids capturing the synchronization context, improving performance in library code.
Why No SynchronizationContext?
ASP.NET Core does not have a SynchronizationContext 1. Library code should still use ConfigureAwait(false) for portability.
GitHub search: repo:dotnet/aspnetcore .ConfigureAwait(false)
Runtime Internals
Task.GetAwaiter 2 returns TaskAwaiter
Task.ConfigureAwait(bool) 3 returns ConfiguredTaskAwaitable
TaskAwaiter struct 4
ConfiguredTaskAwaitable.ConfiguredTaskAwaiter struct 5
State Machine Difference
Without ConfigureAwait(false), the compiler-generated state machine uses TaskAwaiter. With it, the state machine uses ConfiguredTaskAwaitable.ConfiguredTaskAwaiter — the key difference being whether continueOnCapturedContext is set.
AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted 6
AsyncTaskMethodBuilderT.AwaitUnsafeOnCompleted 7
Task.UnsafeSetContinuationForAwait 8
SynchronizationContext source 9
ASP.NET Core Usage
Server.IntegrationTesting RetryHelper 10
HealthCheckPublisherHostedService 11
TaskExtensions.TimeoutAfter 12
System.Private.CoreLib.TaskContinuation 13
TaskAwaiter source 14
AsyncTaskMethodBuilderT.AwaitUnsafeOnCompleted 15