I tried to find an answer for this but couldn\'t. What I was wondering is that on which thread Task.ContinueWith
delegate is called.
For await I know that it tr
This depends on the scheduler that is associated with the continuation. By default, task continuations are scheduled through the Current scheduler, being the TaskScheduler
associated with the currently executing task. When ContinueWith
is not called from within a task, Current
will return the Default scheduler, which is the default TaskScheduler
instance provided by the .NET Framework, and which will schedule your tasks on the thread pool.
If you want to influence this behaviour, you can call one of the ContinueWith
overloads that takes a TaskScheduler
parameter. A common pattern is to pass TaskScheduler.FromCurrentSynchronizationContext()
when creating continuations on the UI thread, as this would cause the continuation to be dispatched back onto the UI thread when executed.
Edit: In reply to your comment: The deadlock may arise if you spawn a child task (intended to run on the thread pool) from a continuation running on the UI thread. In such cases, the child task will inherit the task scheduler from the parent task, which would be bound to the UI thread, causing the child task to run on the UI thread too.
Task.Factory.StartNew(() =>
{
// Do background work.
}).ContinueWith(_ =>
{
// Update UI, then spawn child task to do more background work...
Task.Factory.StartNew(() =>
{
// ...but child task runs on UI thread!
});
},
CancellationToken.None,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
To resolve this, you can use the StartNew
overload that accepts a TaskScheduler
parameter for the child task, and pass TaskScheduler.Default
to it:
// Update UI, then spawn child task to do more background work...
Task.Factory.StartNew(() =>
{
// ...and child task now runs on the thread pool.
},
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default);