Question:
I have a WPF window that triggers a ViewModel command. She, in turn, calls a method from BAL that launches a child thread (it can live from 10 seconds to infinity). This thread generates events as it runs and another event at the very end, announcing the end of work. Since events do not occur on the main thread, the ViewModel uses the Dispatcher for synchronization. If I designed something wrong, I'll be glad to know.
For executing the code in the right thread I use the following code
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(SomeMethod));
But this code does not call the desired method for me in general. Next I tried calling the following code
Dispatcher.CurrentDispatcher.Invoke(new Action(SomeMethod));
As a result, I still got an error, because the execution is not in the main thread. For the sake of testing, I declared the _dispatcher field and initialized it in the constructor while the main thread was running. This dispatcher has already calmly called me everything.
What is it and what should I do? If I suddenly create a ViewModel not in the main thread, then nothing will work for me again.
Answer:
See.
Dispatcher.CurrentDispatcher
returns you the dispatcher for the given thread . Therefore, you have no alternative to keeping a reference to the dispatcher.
Then, VM objects must run on the UI thread (otherwise you won't be able to bind View to them), so they must be constructed on the UI thread too. So, you can count on the fact that in the constructor you will have the correct Dispatcher.CurrentDispatcher
.
Why doesn't a dispatcher created on a background thread work? The dispatcher is an abstraction over the message loop. If a message cycle runs in this thread, then Dispatcher.CurrentDispatcher
returns it to you. If there is no dispatcher for the given thread, a new one is created and attached to the given thread. But this dispatcher is not running yet! The team lies in line and waits. If you run the dispatcher on a background thread, then all commands sent to it will be executed.
However, don't try to do this on a thread pool thread: for the dispatcher to work, a thread must be an STA, and pool threads must not be an STA (and this cannot be changed).
Well, in a good way, you should usually have enough dispatcher on the UI thread.