Consider the following code
Task<T>.Factory.StartNew(() =>
{
// block #1: load some data from local file cache
}
)
.ContinueWith(task =>
{
// block #2: handle success or failure of load-from-cache operation and surface to application
},
cancellationToken,
TaskContinuationOptions.NotOnCanceled,
TaskScheduler.FromCurrentSynchronizationContext()
)
.ContinueWith(task =>
{
// block #3: load data from remote data source
},
TaskContinuationOptions.NotOnCanceled
);
In .NET 4.0, this code executes as I expect: the first block runs in a background thread, then the second block runs, and finally the third block runs.
In .NET 4.5, however, the second block never runs, no matter what happens with the first block (success, fault, or cancellation). And the third block doesn't run either, waiting for the non-starting second block.
Application background
This code is in a WPF application. It's running during the initialization of the application, loading some data necessary for the app to start. On the main thread (where I call this async code from), I am waiting for the result to be populated from code block #3 before continuing. If the remote data call times out, initialization will continue with the data from block #1 (cached).
Things I've tried
- Add the TaskScheduler.FromCurrentSynchronizationContext() to the StartNew call. This causes the code in the StartNew lambda never to execute (and even if it did, I wouldn't want it to run on the main thread).
- Remove the TaskScheduler.FromCurrentSynchronizationContext() from the ContinueWith (and keep either the cancellationToken or the TaskContinuationOptions but not both because no overload supports only those two parameters). This appears to work (the code executes), but I'm concerned about side effects because I'm not sure why it works.