Reputation: 572
After a bit of reading about TaskScheduler
on Parallel Programming with .NET it turns out that a TaskScheduler
can:
Schedule tasks - by using QueueTask
method, which in the example above just Post
s task execution to selected SynchronizationContext
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
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