Pregunta

Having read the phrase "The current SynchronizationContext is a property of the current thread" correct", I am a little confused...

In a C# app code in VS2010, when I type Thread.CurrentThread. I am not finding in the drop-down list of choices given by Intellisense any context-related properties for a thread.

I know that current synchronization context can be got through "= SynchronizationContext.Current;" . But this is not quite fortunate with simultaneously executed in parallel threads, tasks, etc.

Suppose from a console or WPF (*) app I create and launch a few Windows forms in its own main UI threads as well as TPL tasks.

I undermisabovestand that each winform should have its own WindowsFormaSynchronizationContext, WPF should have its own DispatcherSynchronizationContext (subclasses of SynchronizationContext class) instances, the tasks are executed in a ThreadPool with its own synchronization context, LongRunning task orobably will be executed out of thread pool in its own synchronization context...

So, why cannot the SynchronizationContext be defined from thread(s)? All answers to "Get SynchronizationContext from a given Thread" question seem to unanmous in negating tis possibility...

And the last, but not least:
Is the phrase "The current SynchronizationContext is a property of the current thread" correct" correct?
Then, how can I get the value of this property for different particular thread instances?

(*)
Recently, I was given C# WPF app code essentially using winforms.

¿Fue útil?

Solución

This is accurate. The SynchronizationContext.Current property uses the current thread's m_ExecutionContext field. Which is a private field of the Thread class, that's why you don't see it in the IntelliSense dropdown.

It is important it works that way, the default SynchronizationContext doesn't synchronize anything. Its Post() method target runs on a threadpool thread. Marshaling the target call to a specific thread is a very nontrivial thing to do. That requires help from the target thread, it needs to provide a solution to the producer-consumer problem. The generic solution is a loop that retrieves messages from a thread-safe queue. Exactly the way that the UI thread of a Winforms or a WPF app works, they "pump the message loop". Application.Run() starts that loop.

So only the UI thread of such an app can support a synchronization provider that doesn't use threadpool threads to run the Post() delegate target. Accordingly, Winforms and WPF install their own synchronization provider as soon as you create a Form or Window. And only code that runs on the UI thread will see that non-default provider from the SynchronizationContext.Current property.

The consequence is that you must initialize code that need to marshal calls back to the UI thread on the UI thread. So for example creating a BackgroundWorker must be done on the UI thread. Or a task created with TaskScheduler.FromCurrentSynchronizationContext. There can technically be more than one thread that displays UI, whatever thread the init code runs on determines where the Post() delegate target will run. Which probably explains your problem, if your init code runs on a worker thread then the Post() target runs on a threadpool thread. You can pass a reference to the Synchronization.Current object to a worker thread, as long as you obtained that reference on the UI thread.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top