What Does Synchronizationcontext Do

C# What does the Synchronization means in SynchronizationContext?

Synchronization or better for your understanding lets first understand what word Synchronize means.

Don't go with the dictionary definition it will confuse you for now. Instead lets take an oversimplified analogy:

When we walk, our legs are synchronized! That is, they
coordinate/cooperate together to complete an activity called
walking. When left foot touches the ground the right foot leaves it
(or is in process of leaving), and when right foot touches its
vice-versa.

The key takeaway is, both feet have an implicit coordination stating
that other will start (i.e. leave ground) only when first one is
grounded.

So talking in terms of Threads and shared resources. This same analogy applies. All the threads want to work with some shared resource (in our case ground). Thus they need to "coordinate" there usage of the resource.

So when you hear the word "Synchronization", think word coordinate/cooperate. Hope you understand now. I'm purposefully not explaining SynchronizationContext since you state you know it already.

Update: On second though, I should provide you some details here as well, in terms of the analogy:

Hopefully you now understand, what synchronization means! Talking in terms of SynchronizationContext, it simply is a class that allows you to have synchronization (i.e. coordination/cooperation) with existing UI thread's resources (which are mostly UI components and there state). The way this is usually achieved is by putting messages into the UI thread's queue, instead of directly modifying the UI state yourself.

Disclaimer: Don't try the walking analogy yourself, I just lost 2 calories when trying to figure out my leg's synchronization.

Thread Context and Synchronization Context

The synchronization context and thread context are 2 very different things. The synchronization context is a method that can queue a unit of work to a context (mostly a different thread). Here is a quote.

One aspect of SynchronizationContext is that it provides a way to
queue a unit of work to a context. Note that this unit of work is
queued to a context rather than a specific thread. This distinction is
important, because many implementations of SynchronizationContext
aren’t based on a single, specific thread.

A typical example where synchronization context is useful are the GUI applications like WinForms or WPF apps. In WinForms and WPF, only a single UI thread can update the UI elements (textboxes, checkboxes, etc.). If you try to change the content of a textbox from another non-UI thread, the change doesn't happen or exception could be thrown (depending on the UI framework). So in such application the worker non-UI threads need to schedule all changes to the UI elements to the UI thread. And that is what the synchronization context provides. It allows you to post a unit of work (execution of some method) to a different context - the UI thread in this case.

On the other hand the thread context is a structure that contains all information that is necessary to execute thread code by the OS. If the OS needs to change the execution from one thread to another, it executes something that is called a context switch. In context switch the thread that is currently running on the CPU is frozen by the OS and the current state of all CPU registers is stored to a thread context structure of the frozen thread. Here is the actual thread context structure on Windows OS and here on x64 Windows. When the content of all CPU registers is moved to a thread context of the frozen thread, the OS finds another (the most prior) thread that has to run its code, and moves the content of its thread context structure to the CPU registers. After this, the context switch is over and the CPU can execute the code of the most prior thread until another context switch happens.

So the synchronization context and the thread context are two very different concepts. The thread context is the low level structure that allows the OS to switch between the threads while the synchronization context is a mechanism to simplify sending of work items to the different contexts (mostly the different threads).

SynchronizationContext, when does it flow and when does it not?

Under what conditions will the current synchronization context flow with my async operations?

When an async method performs an await, by default it will capture a current context and use that to resume the async method. This context is SynchronizationContext.Current unless it is null, in which case it is TaskScheduler.Current. I describe this behavior in my async intro blog post, my MSDN article on SynchronizationContext, and my MSDN article on async best practices.

Are there differences between Task and others, e.g. Delegate.BeginInvoke?

This behavior is unique to async and await. Delegate.BeginInvoke means "run this delegate on a thread pool thread", so it doesn't propagate the SynchronizationContext. Neither do more modern approaches such as Task.Run.

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?

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).

in the example above, logical call context flows but not synchronization context. any pointers to why this is the case would be interesting.

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.

Does SynchronizationContext no longer flow with ExecutionContext (going from .NET Framework to .NET Core)?

Microsoft has acknowledged that ExecutionContext behavior has indeed changed with .NET Core, and are clarifying this in an update to their official documentation. As part of the change, they've added the following sentence:

Also in .NET Core, the synchronization context does not flow with the execution context, whereas in .NET Framework it may in some cases.



Related Topics



Leave a reply



Submit