@@ -171,6 +171,16 @@ private struct RuntimeAsyncAwaitState
171171 public INotifyCompletion ? Notifier ;
172172 public IValueTaskSourceNotifier ? ValueTaskSourceNotifier ;
173173 public Task ? TaskNotifier ;
174+
175+ public ExecutionContext ? ExecutionContext ;
176+ public SynchronizationContext ? SynchronizationContext ;
177+
178+ public void CaptureContexts ( )
179+ {
180+ Thread curThread = Thread . CurrentThreadAssumedInitialized ;
181+ ExecutionContext = curThread . _executionContext ;
182+ SynchronizationContext = curThread . _synchronizationContext ;
183+ }
174184 }
175185
176186 [ ThreadStatic ]
@@ -240,6 +250,7 @@ private static void TransparentAwait(object o)
240250 state . ValueTaskSourceNotifier = ( IValueTaskSourceNotifier ) o ;
241251 }
242252
253+ state . CaptureContexts ( ) ;
243254 AsyncSuspend ( sentinelContinuation ) ;
244255 }
245256
@@ -541,6 +552,8 @@ public static void HandleSuspended<T, TOps>(T task) where T : Task, ITaskComplet
541552 {
542553 ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState ;
543554
555+ RestoreContextsOnSuspension ( false , state . ExecutionContext , state . SynchronizationContext ) ;
556+
544557 ICriticalNotifyCompletion ? critNotifier = state . CriticalNotifier ;
545558 INotifyCompletion ? notifier = state . Notifier ;
546559 IValueTaskSourceNotifier ? vtsNotifier = state . ValueTaskSourceNotifier ;
@@ -550,6 +563,8 @@ public static void HandleSuspended<T, TOps>(T task) where T : Task, ITaskComplet
550563 state . Notifier = null ;
551564 state . ValueTaskSourceNotifier = null ;
552565 state . TaskNotifier = null ;
566+ state . ExecutionContext = null ;
567+ state . SynchronizationContext = null ;
553568
554569 Continuation sentinelContinuation = state . SentinelContinuation ! ;
555570 Continuation headContinuation = sentinelContinuation . Next ! ;
@@ -794,6 +809,28 @@ private static void RestoreContexts(bool resumed, ExecutionContext? previousExec
794809 }
795810 }
796811
812+ // Restore contexts onto current Thread as we unwind during suspension. We control the code that runs
813+ // during suspension and we do not need to raise ExecutionContext notifications -- we know that it is
814+ // not going to be accessed and that DispatchContinuations will return it back to the leaf's context
815+ // before calling user code, and restore the original contexts with appropriate notifications before
816+ // returning.
817+ private static void RestoreContextsOnSuspension ( bool resumed , ExecutionContext ? previousExecCtx , SynchronizationContext ? previousSyncCtx )
818+ {
819+ if ( ! resumed )
820+ {
821+ Thread thread = Thread . CurrentThreadAssumedInitialized ;
822+ if ( previousSyncCtx != thread . _synchronizationContext )
823+ {
824+ thread . _synchronizationContext = previousSyncCtx ;
825+ }
826+
827+ if ( previousExecCtx != thread . _executionContext )
828+ {
829+ thread . _executionContext = previousExecCtx ;
830+ }
831+ }
832+ }
833+
797834 private static void CaptureContinuationContext ( ref object continuationContext , ref ContinuationFlags flags )
798835 {
799836 SynchronizationContext ? syncCtx = Thread . CurrentThreadAssumedInitialized . _synchronizationContext ;
0 commit comments