Does Task.ContinueWith capture the calling thread context for continuation?

.net, async-await, asynchronous, c#, task-parallel-library

Solution

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.

Problem

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.

Original source