liveBook · Manning

TaskScheduler

As explained in C# Concurrency: Asynchronous and multithreaded programming

TaskScheduler is a .NET abstraction that controls how Task continuations and other task work are scheduled for execution.

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

How C# Concurrency: Asynchronous and multithreaded programming covers it

How deep it goes
Explains scheduler selection and ConfigureAwait rules with C# listings, but does not implement a custom TaskScheduler.
Examples
Uses Task.Delay with ContinueWith, the default scheduler, and TaskScheduler.FromCurrentSynchronizationContext().
What it assumes
Assumes familiarity with async/await and SynchronizationContext while defining TaskScheduler’s role and selection rules.
What you can do after
Operate/configure continuations with explicit schedulers and predict when await uses context, task, or thread-pool execution.
How it connects
Ties TaskScheduler to async/await, SynchronizationContext, ContinueWith, Task.Run, ConfigureAwait, and the thread pool.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C# Concurrency: Asynchronous and multithreaded programming. The section links point to the parts of the book it draws on.