TaskScheduler controls where task continuations and other asynchronous work run. TaskScheduler.Default queues work to the thread pool, while TaskScheduler.FromCurrentSynchronizationContext() routes it through the current context. section 11.6
Use these scheduling rules to reason about continuation behavior:
- Read TaskScheduler.Current to inspect the scheduler associated with the current task; choose schedulers through Task.Run, ContinueWith, and related APIs. section 11.6
- Without ConfigureAwait(false), await prefers a current SynchronizationContext, then an associated TaskScheduler; otherwise it uses the default scheduler. section 11.7
- Use ConfigureAwait(false) deliberately: application code normally retains context, whereas context-independent library code can avoid capturing it. section 11.7
Selecting a continuation scheduler
ContinueWith uses the default thread-pool scheduler when no scheduler is supplied. Passing TaskScheduler.FromCurrentSynchronizationContext() instead schedules the continuation through the current context; it throws when no usable context exists. section 11.6
Task.Delay(500).ContinueWith(t=>Console.WriteLine("Hello"));
Compare the default thread-pool continuation with the context-bound alternative shown in the adjacent listing. section 11.6
Task.Delay(500).ContinueWith(t=>Console.WriteLine("Hello"),
TaskScheduler.FromCurrentSynchronizationContext());
Inspect the explicit scheduler selection that routes the continuation through the current SynchronizationContext. section 11.6
