I have an issue regarding using MVVMLight messenger in a WPF (MVVM) application. In a view I have an element ( LoadingControl ) which visibility property is bound to a viewmodel property ( IsBusy ) by using custom visibility converter. In a viewmodel I change the property value ( IsBusy ) by sending a MVVM message:
Messenger.Default.Send(new LoadingMessage(true));
Here I have the method in a viewmodel which is resgistered to accept LoadingMessage messages, where IsBusy property is changed.
This works fine, however in one of my viewmodel methods where I send this message, UI thread blocks and IsBusy property value changes, but visibility of my UI element LoadingControl doesn't until main operation is not finished, eg:
void Call() {
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate(); // <- this works with UI, too
} // <- this is the place when LoadingControl is shown.
I guess that the problem is because in a viewmodel the execution is not on the ui thread, so I tried to call this directly in a Call() method:
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
IsBusy = true;
});
But this doesn't work too, LoadingControl is not shown until method ends. As I'm not so familiar with multithreading, I supose that there is some other issue here. Any help is appreciated.
Messenger sends message in your thread so you need to wait. I think you need to send message in another thread.
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
});
Another (lighter) way can be to fire and forget your code with Task
Task.Factory.StartNew(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate();
});
If you want to force your Action
to be executed on another thread, you can pass TaskScheduler.Default
to the StartNew()
call. But by doing so, you might fall on Invalid cross-thread access Exception
, since you code no longer executes on the UI thread, but on a Background one. So you might need to Dispatch your code setting view-bounded properties (like your IsBusy
) back to the UI-Thread by using the Dispatcher
:
Application.Current.Dispatcher.BeginInvoke(() =>
{
IsBusy = true;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.