WPF MVVMLight Messenger UI线程问题

时间:2015-02-16 12:50:17

标签: c# wpf multithreading mvvm mvvm-light

我有一个关于在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 直到方法结束才会显示。由于我不太熟悉多线程,所以我认为这里还有其他一些问题。任何帮助表示赞赏。

2 个答案:

答案 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;
}