我有一个关于在WPF(MVVM)应用程序中使用MVVMLight messenger的问题。在视图中,我有一个元素( LoadingControl ),通过使用自定义可见性转换器将可见性属性绑定到viewmodel属性( IsBusy )。在viewmodel中,我通过发送MVVM消息来更改属性值( IsBusy ):
Messenger.Default.Send(new LoadingMessage(true));
此处我在viewmodel中使用了该方法,该方法已重新注册以接受 LoadingMessage 消息,其中 IsBusy 属性已更改。
这很好用,但在我的一个viewmodel方法中,我发送此消息,UI线程块和 IsBusy 属性值更改,但我的UI元素的可见性< strong> LoadingControl 在主要操作未完成之前没有,例如:
void Call() {
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate(); // <- this works with UI, too
} // <- this is the place when LoadingControl is shown.
我想这个问题是因为在一个viewmodel中执行不在ui线程上,所以我试图直接在 Call()方法中调用它:
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
IsBusy = true;
});
但是这也不起作用, LoadingControl 直到方法结束才会显示。由于我不太熟悉多线程,所以我认为这里还有其他一些问题。任何帮助表示赞赏。
答案 0 :(得分:1)
Messenger在您的线程中发送消息,因此您需要等待。我想你需要在另一个帖子中发送消息。
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
});
答案 1 :(得分:1)
另一种(更轻的)方式可能是使用任务
来解雇并忘记您的代码Task.Factory.StartNew(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate();
});
如果您想强制Action
在另一个主题上执行,您可以将TaskScheduler.Default
传递给StartNew()
来电。但是通过这样做,您可能会落在Invalid cross-thread access Exception
上,因为您的代码不再在UI线程上执行,而是在后台线程上执行。因此,您可能需要使用IsBusy
将您的代码设置视图绑定属性(如Dispatcher
)发送回UI-Thread:
Application.Current.Dispatcher.BeginInvoke(() =>
{
IsBusy = true;
}