I'm trying to learn about SynchronizationContext
and friends.
If I set a custom synchronization context at the start of e.g. a console app.
Under what conditions will the current synchronization context flow with my async operations?
Are there differences between Task
and others, e.g. Delegate.BeginInvoke
?
void Main()
{
SynchronizationContext.SetSynchronizationContext(new FooContext());
Action a = () =>
{
var current = SynchronizationContext.Current;
//current is null here
};
a.BeginInvoke(null,null);
...sleep
If I execute stuff on the thread pool, am I forced to assign a synchronization context to that specific thread that is currently executing my work?
When an
async
method performs anawait
, by default it will capture a current context and use that to resume theasync
method. This context isSynchronizationContext.Current
unless it isnull
, in which case it isTaskScheduler.Current
. I describe this behavior in myasync
intro blog post, my MSDN article onSynchronizationContext
, and my MSDN article on async best practices.This behavior is unique to
async
andawait
.Delegate.BeginInvoke
means "run this delegate on a thread pool thread", so it doesn't propagate theSynchronizationContext
. Neither do more modern approaches such asTask.Run
.In general, you shouldn't install a synchronization context on a thread you don't own. If you do place one on a thread pool thread, it should be removed before the thread is returned to the thread pool. More likely, if you're installing a synchronization context, you just shouldn't ever give the thread back (a custom synchronization context is commonly associated with a "main loop" for that thread).
The other contexts are even less documented. Stephen Toub has the definitive post on the subject. In essence, some data such as security must flow; most other data does not.