Reputation: 61696
The Test_Click
below is a simplified version of code which runs on a UI thread (with WindowsFormsSynchronizationContext):
void Test_Click(object sender, EventArgs e)
{
var task = DoNavigationAsync();
task.ContinueWith((t) =>
{
MessageBox.Show("Navigation done!");
}, TaskScheduler.FromCurrentSynchronizationContext());
}
Should I explicitly specify TaskScheduler.FromCurrentSynchronizationContext()
to make sure the continuation action will be executed on the same UI thread? Or does ContinueWith
capture the execution context automatically (thus, making TaskScheduler
argument redundant in this case)?
I assume it doesn't do it by default (unlike await
), but so far I could not find an online resource to confirm this.
Upvotes: 18
Views: 8528
Reputation: 41243
It doesn't use the current synchronization context by default, but TaskScheduler.Current
, as seen in the following decompiled code:
public Task ContinueWith(Action<Task<TResult>> continuationAction)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return this.ContinueWith(continuationAction, TaskScheduler.Current, new CancellationToken(), TaskContinuationOptions.None, ref stackMark);
}
TaskScheduler.Current
is either TaskScheduler.Default
or the TaskScheduler of the current task if the task is a child task. Always specify the task scheduler if you don't want to run into weird problems, or better, use await
if you can.
Upvotes: 13