@@ -224,13 +224,26 @@ private void SignalCompletion()
224224 {
225225 _continuation ( _continuationState ) ;
226226 }
227-
228- return ;
229227 }
230-
231- InvokeSchedulerContinuation ( ) ;
232- return ;
228+ else
229+ {
230+ InvokeSchedulerContinuation ( ) ;
231+ }
232+ }
233+ else
234+ {
235+ InvokeContinuationWithContext ( ) ;
233236 }
237+ }
238+
239+ private void InvokeContinuationWithContext ( )
240+ {
241+ // This is in a helper as the error handling causes the generated asm
242+ // for the surrounding code to become less efficent (stack spills etc)
243+ // and it is an uncommon path.
244+
245+ Debug . Assert ( _continuation != null ) ;
246+ Debug . Assert ( _executionContext != null ) ;
234247
235248 ExecutionContext ? currentContext = ExecutionContext . Capture ( ) ;
236249 // Restore the captured ExecutionContext before executing anything.
@@ -240,61 +253,57 @@ private void SignalCompletion()
240253 {
241254 if ( RunContinuationsAsynchronously )
242255 {
243- ThreadPool . QueueUserWorkItem ( _continuation , _continuationState , preferLocal : true ) ;
244- // Restore the current ExecutionContext.
245- ExecutionContext . Restore ( currentContext ) ;
256+ try
257+ {
258+ ThreadPool . QueueUserWorkItem ( _continuation , _continuationState , preferLocal : true ) ;
259+ }
260+ finally
261+ {
262+ // Restore the current ExecutionContext.
263+ ExecutionContext . Restore ( currentContext ) ;
264+ }
246265 }
247266 else
248267 {
249268 // Running inline may throw; capture the edi if it does as we changed the ExecutionContext,
250269 // so need to restore it back before propagating the throw.
251- ExceptionDispatchInfo ? edi = InvokeInlineContinuation ( ) ;
252- // Restore the current ExecutionContext.
253- ExecutionContext . Restore ( currentContext ) ;
270+ ExceptionDispatchInfo ? edi = null ;
271+ SynchronizationContext ? syncContext = SynchronizationContext . Current ;
272+ try
273+ {
274+ _continuation ( _continuationState ) ;
275+ }
276+ catch ( Exception ex )
277+ {
278+ // Note: we have a "catch" rather than a "finally" because we want
279+ // to stop the first pass of EH here. That way we can restore the previous
280+ // context before any of our callers' EH filters run.
281+ edi = ExceptionDispatchInfo . Capture ( ex ) ;
282+ }
283+ finally
284+ {
285+ // Set sync context back to what it was prior to coming in
286+ SynchronizationContext . SetSynchronizationContext ( syncContext ) ;
287+ // Restore the current ExecutionContext.
288+ ExecutionContext . Restore ( currentContext ) ;
289+ }
290+
254291 // Now rethrow the exception; if there is one.
255292 edi ? . Throw ( ) ;
256293 }
257294
258295 return ;
259296 }
260297
261- InvokeSchedulerContinuation ( ) ;
262- // Restore the current ExecutionContext.
263- ExecutionContext . Restore ( currentContext ) ;
264- }
265-
266- /// <summary>
267- /// Invokes the continuation inline and captures any exception thrown.
268- /// This assumes that if <see cref="_continuation"/> is not null we're already
269- /// running within that <see cref="ExecutionContext"/>.
270- /// </summary>
271- private ExceptionDispatchInfo ? InvokeInlineContinuation ( )
272- {
273- // This is in a helper as the error handling causes the generated asm
274- // for the surrounding code to become less efficent (stack spills etc)
275- // and it is an uncommon path.
276-
277- Debug . Assert ( _continuation != null ) ;
278- Debug . Assert ( _capturedContext == null ) ;
279- Debug . Assert ( ! RunContinuationsAsynchronously ) ;
280-
281- ExceptionDispatchInfo ? edi = null ;
282- SynchronizationContext ? syncContext = SynchronizationContext . Current ;
283298 try
284299 {
285- _continuation ( _continuationState ) ;
300+ InvokeSchedulerContinuation ( ) ;
286301 }
287- catch ( Exception ex )
302+ finally
288303 {
289- // Note: we have a "catch" rather than a "finally" because we want
290- // to stop the first pass of EH here. That way we can restore the previous
291- // context before any of our callers' EH filters run.
292- edi = ExceptionDispatchInfo . Capture ( ex ) ;
304+ // Restore the current ExecutionContext.
305+ ExecutionContext . Restore ( currentContext ) ;
293306 }
294-
295- // Set sync context back to what it was prior to coming in
296- SynchronizationContext . SetSynchronizationContext ( syncContext ) ;
297- return edi ;
298307 }
299308
300309 /// <summary>
0 commit comments