From 59b6c5e7ae244f437b5334dca78828fbecc0c771 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Wed, 16 Mar 2011 00:22:55 -0700 Subject: [PATCH] Fix bug where if a task is Start-ed with a specific scheduler, that scheduler is ignored if it is in a thread owned by another scheduler. Tasks should not be locked to the scheduler that owns the calling thread. Fix bug where TryExecuteTask does not actually try to execute the task. Instead, TryExecuteTaskInline is called, which is abstract. The TpScheduler implementation, the default, then calls the internal method Task.Execute which then actually executes the task. The problem with this is that only 3rd party schedulers, can't actually execute a task, thus making extending TaskScheduler impossible. (Unless they use some serious Mono specific reflection hacks as I am now.) --- mcs/class/corlib/System.Threading.Tasks/Task.cs | 3 ++- .../corlib/System.Threading.Tasks/TaskScheduler.cs | 10 +++++++++- mcs/class/corlib/System.Threading.Tasks/TpScheduler.cs | 10 +--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mcs/class/corlib/System.Threading.Tasks/Task.cs b/mcs/class/corlib/System.Threading.Tasks/Task.cs index 1b24653ff07c..e9168dd9b9d7 100644 --- a/mcs/class/corlib/System.Threading.Tasks/Task.cs +++ b/mcs/class/corlib/System.Threading.Tasks/Task.cs @@ -356,7 +356,8 @@ internal void Schedule () status = TaskStatus.WaitingToRun; // If worker is null it means it is a local one, revert to the old behavior - if (childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) { + // If TaskScheduler.Current is not being used, the scheduler was explicitly provided, so we must use that + if (scheduler != TaskScheduler.Current || childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) { scheduler.QueueTask (this); } else { /* Like the semantic of the ABP paper describe it, we add ourselves to the bottom diff --git a/mcs/class/corlib/System.Threading.Tasks/TaskScheduler.cs b/mcs/class/corlib/System.Threading.Tasks/TaskScheduler.cs index 61966169a6a2..58d99160d9bd 100644 --- a/mcs/class/corlib/System.Threading.Tasks/TaskScheduler.cs +++ b/mcs/class/corlib/System.Threading.Tasks/TaskScheduler.cs @@ -113,7 +113,15 @@ protected internal virtual bool TryDequeue (Task task) internal protected bool TryExecuteTask (Task task) { - return TryExecuteTaskInline (task, false); + if (task.IsCompleted) + return false; + + if (task.Status == TaskStatus.WaitingToRun) { + task.Execute (null); + return true; + } + + return false; } protected abstract bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued); diff --git a/mcs/class/corlib/System.Threading.Tasks/TpScheduler.cs b/mcs/class/corlib/System.Threading.Tasks/TpScheduler.cs index 06ddf9460ecd..c589bb2fdd72 100644 --- a/mcs/class/corlib/System.Threading.Tasks/TpScheduler.cs +++ b/mcs/class/corlib/System.Threading.Tasks/TpScheduler.cs @@ -57,15 +57,7 @@ protected internal override bool TryDequeue (Task task) protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued) { - if (task.IsCompleted) - return false; - - if (task.Status == TaskStatus.WaitingToRun) { - task.Execute (null); - return true; - } - - return false; + return TryExecuteTask(task); } public override int MaximumConcurrencyLevel {