This is another post about a problem that I could have solved much quicker if I’d found the right blog posts. It’s common enough that .net 4.5 will include a new Task.Run method that saves you from this mistake.
The symptom was that a task that was supposed to run in the background while the UI thread did some other work wasn’t starting – it was scheduled but didn’t run.
The reason was that the supposed background task was started from some code that was (further back in the call stack) inside a task that had been scheduled on the UI thread, using a common pattern of specifying the scheduler.
If you’re already inside a task, creating or starting a new task without specifying a scheduler picks up the scheduler of the parent task, not the default scheduler.
public void ButtonClicked()
var onUiThread = TaskScheduler.FromCurrentSynchronizationContext();
var task = new Task(() => DoSomethingInTheBackground());
task.ContinueWith(t => DoSomethingUIRelated(), onUiThread);
public void DoSomethingUIRelated()
var offUiTask = Task.Factory.StartNew(() => SomethingElseForTheBackground());
/// Do some UI-thread stuff
So, on the UI thread, a task is created which calls DoSomethingInBackground. When that is finished, DoSomethingUIRelated is called – on the UI thread by specifying the scheduler onUiThread.
But when the task to call SomethingElseForTheBackground is created, it inherits the UI thread scheduler, and because the UI thread starts a Wait for it, it never gets a chance to run.
The solution is to specify TaskScheduler.Default for offUiTask, or to use the new Task.Run method when .net 4.5 comes along.