WPF MVVMLight Messenger UI 线程问题
WPF MVVMLight Messenger UI thread issue
我有一个关于在 WPF (MVVM) 应用程序中使用 MVVMLight 信使的问题。在视图中,我有一个元素 (LoadingControl),其可见性 属性 绑定到视图模型 属性 (IsBusy) 通过使用自定义可见性转换器。在视图模型中,我通过发送 MVVM 消息更改 属性 值(IsBusy):
Messenger.Default.Send(new LoadingMessage(true));
这里我有一个视图模型中的方法,该方法被注册为接受 LoadingMessage 消息,其中 IsBusy 属性 已更改。
这工作正常,但是在我发送此消息的视图模型方法之一中,UI 线程块和 IsBusy 属性 值发生变化,但我的 UI 元素 LoadingControl 的可见性直到主操作未完成才可见,例如:
void Call() {
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate(); // <- this works with UI, too
} // <- this is the place when LoadingControl is shown.
我猜问题是因为在视图模型中执行不在 ui 线程上,所以我试图在 Call() 中直接调用它方法:
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
IsBusy = true;
});
但这也不起作用,LoadingControl 直到方法结束才显示。由于我对多线程不太熟悉,我想这里还有其他问题。感谢任何帮助。
Messenger 在您的线程中发送消息,因此您需要等待。我想你需要在另一个线程中发送消息。
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
});
另一种(较轻的)方法可以是使用 Task
触发并忘记您的代码
Task.Factory.StartNew(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate();
});
如果你想强制你的 Action
在另一个线程上执行,你可以将 TaskScheduler.Default
传递给 StartNew()
调用。但是这样做,您可能会陷入 Invalid cross-thread access Exception
,因为您的代码不再在 UI 线程上执行,而是在后台线程上执行。因此,您可能需要使用 Dispatcher
将代码设置视图边界属性(如 IsBusy
)分派回 UI-Thread:
Application.Current.Dispatcher.BeginInvoke(() =>
{
IsBusy = true;
}
我有一个关于在 WPF (MVVM) 应用程序中使用 MVVMLight 信使的问题。在视图中,我有一个元素 (LoadingControl),其可见性 属性 绑定到视图模型 属性 (IsBusy) 通过使用自定义可见性转换器。在视图模型中,我通过发送 MVVM 消息更改 属性 值(IsBusy):
Messenger.Default.Send(new LoadingMessage(true));
这里我有一个视图模型中的方法,该方法被注册为接受 LoadingMessage 消息,其中 IsBusy 属性 已更改。
这工作正常,但是在我发送此消息的视图模型方法之一中,UI 线程块和 IsBusy 属性 值发生变化,但我的 UI 元素 LoadingControl 的可见性直到主操作未完成才可见,例如:
void Call() {
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate(); // <- this works with UI, too
} // <- this is the place when LoadingControl is shown.
我猜问题是因为在视图模型中执行不在 ui 线程上,所以我试图在 Call() 中直接调用它方法:
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
IsBusy = true;
});
但这也不起作用,LoadingControl 直到方法结束才显示。由于我对多线程不太熟悉,我想这里还有其他问题。感谢任何帮助。
Messenger 在您的线程中发送消息,因此您需要等待。我想你需要在另一个线程中发送消息。
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
});
另一种(较轻的)方法可以是使用 Task
触发并忘记您的代码Task.Factory.StartNew(() =>
{
Messenger.Default.Send(new LoadingMessage(true));
SomeServiceCall();
Navigate();
});
如果你想强制你的 Action
在另一个线程上执行,你可以将 TaskScheduler.Default
传递给 StartNew()
调用。但是这样做,您可能会陷入 Invalid cross-thread access Exception
,因为您的代码不再在 UI 线程上执行,而是在后台线程上执行。因此,您可能需要使用 Dispatcher
将代码设置视图边界属性(如 IsBusy
)分派回 UI-Thread:
Application.Current.Dispatcher.BeginInvoke(() =>
{
IsBusy = true;
}