Skip to content

Do not capture the SynchronizationContext in ConfigureAwait(ConfigureAwaitOptions) - #630

Merged
SimonCropp merged 2 commits into
mainfrom
fix/configure-await-options
Oct 11, 2026
Merged

SimonCropp merged 2 commits into
mainfrom
fix/configure-await-options

Conversation

@SimonCropp

Copy link
Copy Markdown
Owner

Bug

The Task.ConfigureAwait(ConfigureAwaitOptions) polyfill (and the Task<TResult> overload) implemented ForceYielding and SuppressThrowing with local async wrappers:

static async Task ForceYieldAsync(Task t) { await Task.Yield(); await t; }
static async Task SuppressThrowAsync(Task t) { try { await t; } catch { } }

Both wrappers await without ConfigureAwait(false), so they capture the current SynchronizationContext even when the caller did not pass ContinueOnCapturedContext. await task.ConfigureAwait(ConfigureAwaitOptions.ForceYielding) therefore deadlocks when the context thread is blocked, where the BCL completes. SuppressThrowing also paid for a throw and catch on every faulted or canceled task.

Fix

  • ForceYielding: Task.Run(() => task), which always queues to the thread pool and unwraps to the original outcome.
  • SuppressThrowing: a ContinueWith on TaskScheduler.Default with ExecuteSynchronously that reads Exception (marking it observed) and completes successfully. No exception is thrown.

ContinueOnCapturedContext is still honoured by the final ConfigureAwait(bool) on the resulting task.

Test

Added to PolyfillTests_Task_ConfigureAwait.cs: ForceYielding (both overloads) and SuppressThrowing awaited on a thread whose SynchronizationContext.Post never runs must complete within a timeout. These three timed out on net48 before the fix. Also added coverage for SuppressThrowing on a pending task and ForceYielding propagating a fault.

@SimonCropp SimonCropp added this to the 11.4.4 milestone Oct 11, 2026
@SimonCropp
SimonCropp merged commit 8fbb4de into main Oct 11, 2026
4 checks passed
@SimonCropp
SimonCropp deleted the fix/configure-await-options branch October 11, 2026 22:12
This was referenced Oct 12, 2026
This was referenced Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant