Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of PostMessage in C# to synchronize with the main thread with MVVM?

I must be retarded with searching, because here's another seemingly common problem that I haven't been able to solve.

Here's my problem -- I am using WPF and MVVM, and I have a statemachine that executes in the model. If an error occurs, I need to pass information up to the ViewModel to display the error. This part seems to work okay. When the user clicks the desired behavior, the code in the model continues, and looks at the object the user interacts with to determine what to do next.

The problem is that the model needs to reload a file, which updates the GUI with the contents of said file. Because the model is executing in a thread, you can imagine what I'm going to ask next -- how the hell do you synchronize with the GUI properly? In MFC, I would have used either SendMessage or PostMessage to accomplish the GUI update.

I've read articles for WinForms that suggest using InvokeRequired to automatically call BeginInvoke if necessary. I actually didn't know that BeginInvoke would accomplish what I wanted, so I was encouraged to learn this.

How do I actually call BeginInvoke from my model? Does this method even apply to WPF? I went ahead and implemented a delegate and then called Invoke, but I get the same error that tells me the collection can't be modified from this thread. I also tried BeginInvoke for the hell of it, but I assume that also wouldn't work because it would just launch from a different thread anyway.

Confused. If I have missed something really obvious that's been posted about all over the internet, go ahead and give me a verbal lashing, I probably deserve it.

EDIT - I should probably also add that I am looking for something other than a timer or BackgroundWorker-based solution, unless that's the only way to solve this in WPF / MVVM. Also, I wonder if any of the MVVM toolkits would have facilities for this sort of thing already...

like image 590
Dave Avatar asked Mar 09 '10 17:03

Dave


People also ask

What is the difference between SendMessage and PostMessage?

SendMessage: Sends a message and waits until the procedure which is responsible for the message finishes and returns. PostMessage: Sends a message to the message queue and returns immediately.

What is window PostMessage?

The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.


1 Answers

If you want to schedule some work from a background thread to the UI thread in WPF, use the DispatcherObject. Here's a nice article on how to Build More Responsive Apps with the Dispatcher.

Update: Note that if you use an event to send notifications from the Model to the ViewModel, you still need to switch to the UI thread somewhere. Whether that switch should be in the Model or the ViewModel is a good design discussion, but it's orthogonal to your question.

The event will be raised on the corresponding Dispatcher thread. Since you need to get to the UI thread, you need to use a Dispatcher that is created on the UI thread. The easiest way to get one is to use the DispatcherObject.Dispatcher property on one of the UI elements. The alternative is to create one in your Model or ViewModel. If you are a design purist, I would suggest you create the Dispatcher in your Model and dispatch the call back to the UI thread before you raise the event to which the ViewModel is listening. This way all the thread switching and management is contained in your Model and the ViewModel works as a single-threaded on the UI thread only.

like image 153
Franci Penov Avatar answered Sep 19 '22 13:09

Franci Penov