Fix Task so that RunContinuationsAsynchronously flag works with all types of continuation
authorAlfredo Menendez Sancho <alfremen@microsoft.com>
Thu, 12 Nov 2015 02:31:34 +0000 (18:31 -0800)
committerAlfredo Menendez Sancho <alfremen@microsoft.com>
Thu, 12 Nov 2015 02:31:34 +0000 (18:31 -0800)
src/mscorlib/src/System/Threading/Tasks/Task.cs

index ebd8c2b..2194300 100644 (file)
@@ -3610,7 +3610,14 @@ namespace System.Threading.Tasks
                 ITaskCompletionAction singleTaskCompletionAction = continuationObject as ITaskCompletionAction;
                 if (singleTaskCompletionAction != null)
                 {
-                    singleTaskCompletionAction.Invoke(this);
+                    if (bCanInlineContinuations)
+                    {
+                        singleTaskCompletionAction.Invoke(this);
+                    }
+                    else
+                    {
+                        ThreadPool.UnsafeQueueCustomWorkItem(new CompletionActionInvoker(singleTaskCompletionAction, this), forceGlobal: false);
+                    }
                     LogFinishCompletionNotification();
                     return;
                 }
@@ -3687,7 +3694,15 @@ namespace System.Threading.Tasks
                         {
                             Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
                             var action = (ITaskCompletionAction)currentContinuation;
-                            action.Invoke(this);
+
+                            if (bCanInlineContinuations)
+                            {
+                                action.Invoke(this);
+                            }
+                            else
+                            {
+                                ThreadPool.UnsafeQueueCustomWorkItem(new CompletionActionInvoker(action, this), forceGlobal: false);
+                            }
                         }
                     }
                 }
@@ -6650,6 +6665,28 @@ namespace System.Threading.Tasks
 
     }
 
+    internal sealed class CompletionActionInvoker : IThreadPoolWorkItem
+    {
+        private readonly ITaskCompletionAction m_action;
+        private readonly Task m_completingTask;
+
+        internal CompletionActionInvoker(ITaskCompletionAction action, Task completingTask)
+        {
+            m_action = action;
+            m_completingTask = completingTask;
+        }
+
+        public void ExecuteWorkItem()
+        {
+            m_action.Invoke(m_completingTask);
+        }
+
+        public void MarkAborted(ThreadAbortException tae)
+        {
+            /* NOP */
+        }
+    }
+
     // Proxy class for better debugging experience
     internal class SystemThreadingTasks_TaskDebugView
     {