Cannot 'LoadModule' in seperate thread !

Topics: Prism v4 - WPF 4
Jul 23, 2012 at 10:17 AM

I have a WPF application in PRISM architecture.

I have a 'Login View' that is shown in the 'Main Region' when the app loads.

When the user presses 'Login' - I connect to a WCF service, authenticate the user, and get a list of roles for that user from the service.

Then - according to the user's roles - I load different modules, using the 'Module Manager'.

Problem is - I want all the work after the 'Login' button is pressed to be done in a separate thread, because it might take time to connect to the service etc, and I don't want the UI to be frozen.

But - if I put the code to 'connect, authenticate, get roles, load modules' in a separate thread - I get an exception when I call '_moduleManager.LoadModule' that says:

 The calling thread must be STA, because many UI components require this.

How can I solve this ?

I have tried different solutions.
I have tried to set the new thread's 'Apartment State = STA' and it didn't help.
I thought about saving the 'Dispatcher' object in the constructor of the View-Model, and then do 'dispatcher.Invoke' when I call 'LoadModule', but that is bad design (View-Model should not use Dispatcher, and also it is bad for testing).


Any ideas how I can solve this ??

Only the 'LoadModule' gives me grief, all the other stuff works fine.

Developer
Jul 23, 2012 at 7:08 PM

Hi,

Based on my understanding, the loading of modules should be done in the "main" thread of your application. In this case, a possible approach could be to execute the code to "connect, authenticate and get roles" in the separated thread, pass the list of modules that should be loaded to the "main" thread and load the modules there. Usually, the thread Dispatcher is used to achieve this kind of functionality.

Also, as far as I know, it's not required for the aforementioned functionality to be in your view model. For example, you could implement a service that could be in charge of connecting, authenticating, getting the roles and loading the modules (in its corresponding thread). The view model then could simply consume this service, so it would not be aware of the aforementioned logic.

You can find more information in the following section of the Prism documentation:

Also, I believe you might find the MVVM RI provided by Prism useful, as it provides examples of asynchronous interactions when using MVVM:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Jul 24, 2012 at 6:39 AM

Can you please provide a code sample with the dispatcher doing such a thing ?
Isn't it bad to have code using the Dispatcher in my View-Model (in respect of testability) ? 

Also - it seems like you contradicted yourself a bit.

 

You said : "Based on my understanding, the loading of modules should be done in the "main" thread of your application"

and then you said : "you could implement a service that could be in charge of connecting, authenticating, getting the roles and loading the modules (in its corresponding thread)".


So can I or can't I load the modules in a separate thread ?

Developer
Jul 25, 2012 at 6:54 PM

Hi,

Sorry for the misunderstanding. When I wrote "(in its corresponding thread)" I meant the "main" thread, which is the thread in which the modules should be loaded.

Regarding the approach I mentioned before about using a service to obtain the list of modules to be loaded asynchronously, you can find a mock-up sample in my SkyDrive account named SimpleSeparateThreadSample:

In this mock-up sample, a mocked ModuleListService is defined which receives a callback and after 3 seconds returns the list of modules to be loaded (in this case, only one) invoking the aforementioned callback in the "main" thread. The view model is not aware of this and only consumes the service. This service uses a new Thread to mock an asynchronous action, but in a real scenario this could be, for example, a call to an asynchronous WCF Service.

Again, this is only a possible approach; which approach you should use will depend mostly of your personal preferences and the requirements of your scenario.

Regarding the usage of the Dispatcher in the view model, I am not aware if it's a "bad" pattern or not. However, as mentioned in the following blog post by Kent Boogaart, this should not complicate the testability of your view model:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini