High-level notes on the SynchronizationContext
DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT
Questions to Answer
- How do we safely do a fire-and-forget with async/await?
- On what thread does the
SynchronizationContext
itself run? - How do we access the
SynchronizationContext
? - How does the
SynchronizationContext
differ from theIAsyncStateMachine
? - What state does the
SynchronizationContext
capture?
Historical Context
ISynchronizeInvoke
standardizes use of the Windows Message Queue.
- queues work to a thread
- checks whether synchronization is necessary
- lets a source thread queue a delegate to a target thread
- if source is already target, does not bother queuing
- source can optionally wait for delegate completion
SynchronizationContext
replaces it to support ASP.NET async pages.
- queues work to a context (NOT to a thread)
- does NOT check whether synchronization is necessary
- maintains a count of outstanding operations
- every thread has an current context
SynchronizationContext
Implementations
WindowsFormsSynchronizationContext
& DispatcherSynchronizationContext
- execute delegates on a single thread
- execute delegates one at a time
- execute delegates in queued order
Default SynchronizationContext
- executes delegates on any thread from the process's thread pool
execute delegates one at a timeexecute delegates in queued order
AspNetSynchronizationContext
- execute delegates on any thread from the process's thread pool
- execute delegates one at a time
execute delegates in queued order- maintains the identity & culture of the initial thread
The Task Parallel Library (TPL)
- uses
Task
objects as units of work - executes tasks with the
TaskScheduler
- the behavior of the default
TaskScheduler
... - matches the behavior of the default
SynchronizationContext
- any thread
- any time
- any order
async/await
- in addition to creating a state machine (de-compiled here),
- the
await
point captures the currentSynchronizationContext
- unless the current context is null
- in which case it captures the current
TaskScheduler
ConfigureAwait(bool)
true
try to use the captured context to run the continuationfalse
not to use the captured context to run the continuation
Marshalling among Threads with Async/Await
- to marshal means "to transform data from one form to another"
- in the context of threading, to marshal means
- to transform a unit of work, and
- to send it to another thread
await
asks for the currentSynchronizationContext
- then on continuation,
- if the current context was null:
await
runs the operation in the originalTaskScheduler
- else:
await
posts the operation to the captured context
- the decision of where/when to run the operation belongs to the implementation of the
SynchronizationContext
andTaskScheduler
.
Schedulers
Give a scheduler some work and the scheduler determines:
- when to run that work
- where to run that work
Some schedulers:
- message pump (aka message loop, event loop, run loop)
System.Threading.ThreadPool
System.Threading.SynchronizationContext
System.Threading.Tasks.TaskScheduler
System.Reactive.Concurrency.EventLoopScheduler
System.Reactive.Concurrency.IScheduler
System.Windows.Threading.Dispatcher
SynchronizationContext
- is an abstract class that represents a scheduler
- has several virtual methods
- e.g.
SynchronizationContext.Post()
- accepts a delegate and
- decides when/where to run it
TaskScheduler
- uses the
ThreadPool
to queue and execute work - the
ThreadPool
receivesTasks
as short-lived units of work
ThreadPool
- maintains a global work queue
- it is FIFO
- it receives top-level tasks
- it de-queues work to the next available thread
- maintains local work queues
- it is LIFO (i.e. like a stack)
- it receives nested tasks
- it is specific to the parent task's thread
White Elephant
- an
ExecutionContext
contains a currentSynchronizationContext
- the
SynchronizationContext
, among other things, determines the thread on which to run a delegate - delegate / unit of work / operation are vaguely synonymous
References
https://msdn.microsoft.com/magazine/gg598924.aspx
http://stackoverflow.com/questions/5600761/what-is-marshalling-what-is-happening-when-something-is-marshalled
https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/
https://msdn.microsoft.com/library/system.threading.tasks.taskscheduler.aspx