Reputation: 1534
I have an assembly that runs under an STA thread within a sandbox from a third party, within this thread i have created a duplex WCF client that needs to execute methods on the original STA thread.
The current implementation works fine, within the Duplex callback i obtain the synchronization context of the STA thread as follows and use it to Post back to the STA thread:
private readonly SynchronizationContext _syncContext = AsyncOperationManager.SynchronizationContext;
This all runs within a WinForm initialised in the STA thread, great...but i need to move the WCF duplex proxy so it instead runs under a class instance within the main STA thread. When i remove the winform i end up getting a completely new thread from the above SynchronizationContext.
To clarify:
Winforms:-
Without WinForm (class instance):-
Executing on thread 11 instead of 1 means my methods fail to execute properly within the sandbox, there is no difference in the code between variants other than that one runs under a winform. Does anyone know how i can keep the duplex callback method execution in the main STA thread without using the winform?
Upvotes: 1
Views: 596
Reputation: 15227
You're acquiring the synchronization context using the AsyncOperationManager.SynchronizationContext
property. That property uses SynchronizationContext.Current
under the hood.
That means, the obtained SynchronizationContext
depends on the environment you're accessing the property in:
As you can read in the docs:
The default implementation is the free-threaded implementation.
So, if the current thread's synchronization context is not set, you will get a default free-threaded SynchronizationContext
instance. It will Send
callbacks by synchronous execution on caller thread and Post
callbacks to the ThreadPool
(so "random" worker threads will pick them up).
In a Windows Forms app, the main thread's SynchronizationContext
will be initialized to a WindowsFormsSynchronizationContext
instance for you. That instance will Post
the callbacks to the main UI thread.
In a WPF app, this will be a DispatcherSynchronizationContext
.
In a console app, there will be no SynchronizationContext
for the main thread. Thus, the free-threaded option I mentioned above kicks in, so you get a free-threaded SynchronizationContext
instance that posts to the ThreadPool
. That pretty much explains the behavior you observe.
If you need that synchronization, you can implement your own thread-affine SynchronizationContext
for the main thread of your console app. That is not easy though. In a console app, you have no message loop and no dispatcher that could manage the callback queue. You can take a look on this great answer by Stephen Cleary for an idea of an asynchronous SynchronizationContext
. You will need to create a 'main loop' manually though.
Upvotes: 5