user4205580
user4205580

Reputation: 572

TaskScheduler - executing continuations

After a bit of reading about TaskScheduler on Parallel Programming with .NET it turns out that a TaskScheduler can:

  1. Schedule tasks - by using QueueTask method, which in the example above just Posts task execution to selected SynchronizationContext

  2. Schedule continuations through the lower-level scheduler associated with the currently running framework (SynchronizationContext).

Is 2. in any way related to CotninueWith method of Task? I obviously understand 1., but don't see how 2. is true for TaskScheduler. In what method of TaskScheduler would that happen?

Upvotes: 4

Views: 257

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

Schedule continuations through the lower-level scheduler associated with the currently running framework (SynchronizationContext).

I think you got it mixed a little. You can use a given TaskScheduler and execute a continuation on it, not the other way around. That is exactly what this snippet from the post you shared does:

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
var tf = Task.Factory; 

blendedImage.ContinueWith(_ => 
{ 
    pictureBox1.Image = blendedImage.Result; 
}, ui); 

It tells the Task.ContinueWith to use the UI TaskScheduler (which was provided by calling TaskScheduler.FromCurrentSynchronizationContext()) earlier in order to invoke the continuation on a particular context, this time being the UI message loop.

If you really want to get down to the details, when you pass a TaskScheduler to ContinueWith, it ends up passing it to a class called StandardTaskContinuation which has the following Run method that ends up calling TaskScheduler.InternalTaskQueue:

internal void ScheduleAndStart(bool needsProtection)
{
    if (needsProtection)
    {
        if (!this.MarkStarted())
        {
            return;
        }
    }
    else
    {
        this.m_stateFlags |= 65536;
    }
    if (Task.s_asyncDebuggingEnabled)
    {
        Task.AddToActiveTasks(this);
    }
    if (AsyncCausalityTracer.LoggingOn && 
       (this.Options & (TaskCreationOptions)512) == TaskCreationOptions.None)
    {
        AsyncCausalityTracer.TraceOperationCreation(
            CausalityTraceLevel.Required, this.Id, "Task: " +
            ((Delegate)this.m_action).Method.Name, 0uL);
    }
    try
    {
        this.m_taskScheduler.InternalQueueTask(this);
    }
    catch (ThreadAbortException exceptionObject)
    {
        this.AddException(exceptionObject);
        this.FinishThreadAbortedTask(true, false);
    }
    catch (Exception arg_93_0)
    {
        TaskSchedulerException ex = new TaskSchedulerException(arg_93_0);
        this.AddException(ex);
        this.Finish(false);
        if ((this.Options & (TaskCreationOptions)512) == TaskCreationOptions.None)
        {
            this.m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
        }
        throw ex;
    }
}

Upvotes: 4

Related Questions