From 702670e3040fa2c49782da16409e557409ada445 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 6 Oct 2017 18:38:00 -0400 Subject: [PATCH] Fix handling of continuations for captured context My recent delegate optimization for async methods introduced a race condition that breaks posting back to a captured context. If the awaited task completes between the time we check IsCompleted and when we try to store the continuation into the Task, we need to queue the continuation for execution, but my change incorrectly queued it to the thread pool rather than to the captured context. --- src/mscorlib/src/System/Threading/Tasks/Task.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mscorlib/src/System/Threading/Tasks/Task.cs b/src/mscorlib/src/System/Threading/Tasks/Task.cs index e3dd01c..aed2c3b 100644 --- a/src/mscorlib/src/System/Threading/Tasks/Task.cs +++ b/src/mscorlib/src/System/Threading/Tasks/Task.cs @@ -2644,10 +2644,10 @@ namespace System.Threading.Tasks SynchronizationContext syncCtx = SynchronizationContext.CurrentNoFlow; if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext)) { - Action moveNextAction = stateMachineBox.MoveNextAction; - if (!AddTaskContinuation(new SynchronizationContextAwaitTaskContinuation(syncCtx, moveNextAction, flowExecutionContext: false), addBeforeOthers: false)) + var tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, stateMachineBox.MoveNextAction, flowExecutionContext: false); + if (!AddTaskContinuation(tc, addBeforeOthers: false)) { - AwaitTaskContinuation.UnsafeScheduleAction(moveNextAction, this); + tc.Run(this, canInlineContinuationTask: false); } return; } @@ -2656,10 +2656,10 @@ namespace System.Threading.Tasks TaskScheduler scheduler = TaskScheduler.InternalCurrent; if (scheduler != null && scheduler != TaskScheduler.Default) { - Action moveNextAction = stateMachineBox.MoveNextAction; - if (!AddTaskContinuation(new TaskSchedulerAwaitTaskContinuation(scheduler, moveNextAction, flowExecutionContext: false), addBeforeOthers: false)) + var tc = new TaskSchedulerAwaitTaskContinuation(scheduler, stateMachineBox.MoveNextAction, flowExecutionContext: false); + if (!AddTaskContinuation(tc, addBeforeOthers: false)) { - AwaitTaskContinuation.UnsafeScheduleAction(moveNextAction, this); + tc.Run(this, canInlineContinuationTask: false); } return; } -- 2.7.4