Search
Close this search box.

Creating your own dispatcher thread

I haven’t posted here in a while and see the final result is ridiculous… Guess I’ll have to learn those fancy posting tags…. Alright I know there are a lot of tools out there built for integration test purpose but I figured I would post what I think could be considered a poor man’s solution for integration testing but which works amazingly well… I’m using MSTest as the harness for starting my integration test and the solution I’m building is a WPF 3 tiered app built using the MVVM pattern. So basically I’m supposed to instantiate ViewModel classes and populate their fields and collections so I can effectively fire up the appropriate commands and get my test to actually do something. My main problem is that these ViewModels are full of async and await calls which means those commands have to be fired on a different thread than the thread on which the unit test runs, otherwise, my unit test end before the async code completes. This also means I need to wait for that other thread to finish before I can go on with the rest of my integration test. Add to that a bit more complexity to the mix, our homemade set of tools to fire commands using async and await do force that call to be made on the dispatcher thread of WPF… Is there such a thing as a dispatcher thread when running tests using MSTest???? Nope… So you need to create your own dispatcher thread and tell the .net framework that this new thread is the one that should be considered the dispatcher thread… Here’s the code I used for that and a few justifications as of why I did this and that : internal Thread CreateDispatcher() { ManualResetEvent dispatcherReadyEvent = new ManualResetEvent(false); var dispatcherThread = new Thread(() => { // This is here just to force the dispatcher infrastructure to be setup on this thread Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => { })); // Run the dispatcher so it starts processing the message loop dispatcherReadyEvent.Set(); Dispatcher.Run(); }); dispatcherThread.SetApartmentState(ApartmentState.STA); dispatcherThread.IsBackground = true; dispatcherThread.Start(); dispatcherReadyEvent.WaitOne(); SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext()); return dispatcherThread; } Now a few comments on the above… Why do I need to synchronize my code with a ManualResetEvent? Because I need to make sur the SetSynchronizationContext call is executed after the threadstart action executer this very important line Dispatcher.CurrentDispatcher. Note that the action inside that call does not need to be done executing, in fact in my case the action does nothing! Simply touching the Dispatcher.CurrentDispatcher method is enough to set the current thread as the dispatcher thread. Another very important thing for me was to set the current apartment of the new dispatcher thread to STA so it would reflect the real apartment of a UI thread in .net. Now all I need to do going forward is to pass this thread around to this method when invoking async actions: Dispatcher.FromThread(myDispatcher).Invoke(someAction). Of course, you’ll need a way to wait for this newly fired action to complete but that I cannot help you with and your code should already provide sufficient ways to do so… Hope this will help someone out there! Happy coding all.

This article is part of the GWB Archives. Original Author: Vincent Grondin

Related Posts