Get SynchronizationContext from a given thread

It seems I did not find how to get the SynchronizationContext this Thread :

 Thread uiThread = UIConfiguration.UIThread; SynchronizationContext context = uiThread.Huh?; 

Why do I need it?

Because I need to publish to UIThread from various places around the interface. Therefore, I defined a static property in the UIConfiguration class. I set this property in the Program.Main method:

 UIConfiguration.UIThread = Thread.CurrentThread; 

At that very moment, I can be sure that I have the correct stream, however I cannot set a static property, for example

 UIConfiguration.SynchronizationContext = SynchronizationContext.Current 

since the implementation of this WinForms class is not yet installed. Since each thread has its own SynchronizationContext, should it be accessible for extraction from the given Thread object, or am I completely wrong?

+7
multithreading c # synchronizationcontext
source share
5 answers

It's impossible. The problem is that a SynchronizationContext and a Thread are really two completely separate concepts.

While it is true that Windows Forms and WPF set the SynchronizationContext for the main thread, most other threads do not. For example, none of the threads in ThreadPool contain their own SynchronizationContext (unless, of course, you set your own).

It is also possible that the SynchronizationContext completely unrelated to threads and threads. The synchronization context can be easily configured to synchronize with an external service or with a full thread pool, etc.

In your case, I would recommend setting UIConfiguration.SynchronizationContext to the Loaded initial main event. The context is guaranteed to be launched at this point and will be unusable until, in any case, the message pump is started.

+12
source share

I know this is an old question, and apologize for necro, but I only found a solution to this problem that I thought could be useful for those of us who were looking for this (and this does not require instance control).

Basically, you can create an instance of WindowsFormsSynchronizationContext and set the context manually in your Main function, for example:

  _UISyncContext = new WindowsFormsSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(_UISyncContext); 

I did this in my application and it works fine without problems. However, I must indicate that my Main marked with STAThread, so I'm not sure if this will work anyway (or even if it is necessary) if MTAThread is checked instead of Main .

EDIT: I forgot to mention this, but _UISyncContext already defined at the module level in the Program class in my application.

+7
source share

I found for myself the most concise and useful for me the following excerpts from the book by Alex Davis "Async in C # 5.0. O'Reilly Publ., 2012", pp. 48-49:

  • " SynchronizationContext is a class provided by the .NET Framework that has the ability to run code in a specific stream type .
    There are various synchronization contexts used by .NET, the most important of which are the user interface thread contexts used by WinForms and WPF.

  • " SynchronizationContext instances themselves don't do anything very useful, so all actual instances of it are usually subclasses.

    It also has static elements that allow you to read and manage the current SynchronizationContext .

    The current SynchronizationContext is a property of the current thread.

    The idea is that at any time when you are working in a special thread, you can get the current SynchronizationContext and save it. Later you can use it to run the code in a special thread that you started. All this should be possible without having to know exactly which thread you started from, while you can use the SynchronizationContext, you can return to it .

    An important SynchronizationContext method is Post , which can make the delegate work in the right context. "
    ,

  • " Some SynchronizationContexts encapsulate a single thread, such as a user interface thread .
    Some encapsulate a specific type of stream — for example, a pool of threads — but can select any of these streams to send a delegate to . Some do not actually change which thread the code runs on, but are used only for monitoring, for example, for the ASP.NET synchronization context.

+4
source share

I do not believe that each thread has its own SynchronizationContext - it just has a thread-local SynchronizationContext .

Why don't you just set the UIConfiguration.UIThread to the Loaded event of your form or something like that?

+2
source share

Full and working extension methods for getting a SynchronizationContext from Thread or ExecutionContext (or null if none), or DispatcherSynchronizationContext from Dispatcher . Tested on .NET 4.6.2 .

 using Ectx = ExecutionContext; using Sctx = SynchronizationContext; using Dctx = DispatcherSynchronizationContext; public static class _ext { // DispatcherSynchronizationContext from Dispatcher public static Dctx GetSyncCtx(this Dispatcher d) => d?.Thread.GetSyncCtx() as Dctx; // SynchronizationContext from Thread public static Sctx GetSyncCtx(this Thread th) => th?.ExecutionContext?.GetSyncCtx(); // SynchronizationContext from ExecutionContext public static Sctx GetSyncCtx(this Ectx x) => __get(x); /* ... continued below ... */ } 

All of the above functions end up calling the __get code shown below, which requires some explanation.

Note that __get is a static field pre-initialized by a drop lambda block. This allows us to gently intercept the first caller just to run a one-time initialization, which prepares the tiny and constant replacement delegate much faster and without reflection.

The final act for the fatal initialization effort is to replace the replacement with "__get", which at the same time tragically means that the code discards itself without leaving a trace, and all subsequent callers are directly sent to DynamicMethod , not even a hint of bypass logic.

 static Func<Ectx, Sctx> __get = arg => { // Hijack the first caller to do initialization... var fi = typeof(Ectx).GetField( "_syncContext", // private field in 'ExecutionContext' BindingFlags.NonPublic|BindingFlags.Instance); var dm = new DynamicMethod( "foo", // (any name) typeof(Sctx), // getter return type new[] { typeof(Ectx) }, // type of getter single arg typeof(Ectx), // "owner" type true); // allow private field access var il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, fi); il.Emit(OpCodes.Ret); // ...now replace ourself... __get = (Func<Ectx, Sctx>)dm.CreateDelegate(typeof(Func<Ectx, Sctx>)); // oh yeah, don't forget to handle the first caller request return __get(arg); // ...never to come back here again. SAD! }; 

The nice part is the very end, where - in order to actually get the value for the pre-rooted first caller - the function supposedly calls itself its own argument, but avoids recursion, replacing itself directly earlier.

There is no particular reason to demonstrate this unusual method for the specific SynchronizationContext problem discussed on this page. Capturing the _syncContext field from an ExecutionContext can be easily and trivially addressed by traditional reflection (plus some method of freezing the extension method). But I thought that I would share this approach, which I personally used for quite some time, because it is also easily adaptable and equally widely applicable to such cases.

This is especially important when extreme performance is required when accessing a non-public field. I think I initially used this on a QPC-based frequency counter, where the field was read in a narrow loop that repeated every 20 or 25 nanoseconds, which would not be possible with normal reflection.

This concludes the main answer, but below I have included some interesting points that are less relevant to the research request, more similar to the technique just demonstrated.


Runtime Challenges

For clarity, I divided the steps of “installing swap” and “first usage” into two separate lines in the code shown above, unlike what I have in my own code (in the next version, the choice from main memory is also avoided compared to previous, potentially implying thread safety, see the detailed discussion below):

 return (__get = (Func<Ectx, Sctx>)dm.CreateDel...(...))(arg); 

In other words, all callers, including the first, select the value in exactly the same way, and the reflection code is never used for this. It records only the getter replacement. Provided by il-visualizer , we can see the body of this DynamicMethod in the debugger at runtime:

ldarg.0 <br> ldfld SyncContext _syncContext / ExecutionContext <br> ret

Non-latching security

I should note that replacing in the body of the function is a completely thread safe operation, given the .NET memory model and the philosophy lock. The latter contributes to guarantees of progress forward with the possible expenditure of duplicate or excess work. Multitrack racing for initialization is correctly allowed on a fully substantiated theoretical basis:

  • the race entry point (initialization code) is configured and protected globally (using the .NET loader), so that (several) riders (if any) enter the same initializer, which can never be considered null .
  • several racing products (getters) are always logically identical, so it does not matter which rider (or a later non-racing caller) can pick up or even win any rider using the one they produced themselves;
  • each installation swap is a single IntPtr sized repository that is guaranteed to be atomic for any corresponding platform bit;
  • finally, and technically absolutely critical for perfect formal correctness, the work products of the "losers" are restored by the GC and thus do not leak. In this type of race , the losers are every rider except the last finisher (since all other efforts become careless and totally rewritten with an identical result).

Although I believe that these points together fully protect the code written under any possible circumstances, if you are still suspicious or afraid of a general conclusion, you can always add an additional layer of armor protection:

 var tmp = (Func<Ectx, Sctx>)dm.CreateDelegate(typeof(Func<Ectx, Sctx>)); Thread.MemoryBarrier(); __get = tmp; return tmp(arg); 

This is just a paranoid version. As with the earlier condensed single layer, the .NET memory model ensures that there is exactly one store - and zero samples - at the __get location. (The full extended example at the top makes an additional sample of the main memory, but still sounds thanks to the second marker point). As I already mentioned, none of this should be necessary for correctness, but theoretically it can give a minimal performance bonus: after finishing the race earlier, an aggressive flash could, in an extremely rare case, prevent the caller from re-calling the dirty cache line unnecessarily (but again harmless).

Double thunking

The call to the final, ultrafast method is still thunked through the static extension methods shown earlier. This is because we also need to somehow introduce the entry points that actually exist at compile time for the compiler to bind and distribute metadata. Double-Thunk is a small price to pay for the overwhelming convenience of highly typed metadata and intellisense in the IDE for customized code that cannot actually be resolved before execution. Nevertheless, it works at least as fast as a statically compiled code, faster, which makes a bunch of reflection on every call, so we get the best of both worlds!

+1
source share

All Articles