To fix your example specifically:
public void Activate()
{
Task.Factory.StartNew(() =>
{
//executes in thread pool.
return GetSomething(); // returns a Task.
}) // returns a Task<Task>.
.Unwrap() // "unwraps" the outer task, returning a proxy
// for the inner one returned by GetSomething().
.ContinueWith(task =>
{
// executes in UI thread.
Prop = task.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
This will work, but it's old-school.
The modern way to run something on a background thread and dispatch back to UI thread is to use Task.Run()
, async
, and await
:
async void Activate()
{
Prop = await Task.Run(() => GetSomething());
}
Task.Run
will start something in a thread pool thread. When you await
something, it automatically comes back in on the execution context which started it. In this case, your UI thread.
You should generally never need to call Start()
. Prefer async
methods, Task.Run
, and Task.Factory.StartNew
-- all of which start the tasks automatically. Continuations created with await
or ContinueWith
are also started automatically when their parent completes.