使用MVVM Light进行多线程处理的推荐方法是什么。 我有一个模型,该模型具有布尔属性Busy
public bool Busy
{
get { return busy_; }
set
{
Set(nameof(Busy), ref busy_, value, broadcast: true);
}
}
我的视图模型直接为视图发布模型(该模型是继承MVVM Light的ViewModelBase),因此视图直接绑定到模型的busy属性。
如果我总是从UI线程调用模型,那么一切都很好。但是,如果我在视图模型中执行以下操作,则它可能会在其他线程上执行
Task.Factory.StartNew(() =>
{
model_.SomeFunctionThatWillSetBusyDuringItsExecution();
});
然后,当然是从非UI线程设置“忙”,然后绑定失败并且应用程序崩溃。如果我碰巧在属性设置器中使用Messenger,似乎Messenger也不会自动将Messenger处理程序代码分派到UI线程。
我意识到MVVM Light中有一个DispatcherHelper,但对于绑定似乎没有帮助。如果我将属性更改为
public bool Busy
{
get { return busy_; }
set
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Set(nameof(Busy), ref busy_, value, broadcast: true);
});
}
}
我仍然遇到异常,由于绑定源不在正确的线程上,导致应用程序崩溃。所以我的问题很简单,在MVVM Light中进行这种多线程处理的推荐方法是什么?
我也尝试过使用syncronizationContext。
syncContext_.Post(() =>
{
Set(nameof(Busy), ref busy_, value, broadcast: true);
}, null);
如果调用始终来自非UI线程,则该方法有效。如果调用已经从UI线程进行,则syncContext.Post导致在ViewModel方法中的所有代码完成之前才调用Set()函数。这意味着可能无法为其余代码正确更新繁忙状态。因此,这不是理想的解决方案。
感谢您在此主题上的帮助。
答案 0 :(得分:0)
我没有在属性中添加DispatcherHelper代码,而是在修改属性的所有位置添加了它。这样看来效果很好。
唯一的问题是,由于有人将工作分配给UI线程,因此,如果部分视图模型方法已在UI线程上运行,则ViewModel中的代码将不会获得更新状态。我找到了一种方法,可以确保UI线程处理其Messenger队列,尽管要确保它的更新状态为Busy。它不是最好的解决方案,由于所有上下文切换,它可能会对性能产生不良影响,但至少它可以起作用,并且它是一个简单的方法。
强制UI线程处理其队列中所有消息的代码
DispatcherHelper.UIDispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);
如果有更好的解决方法,请告诉我。否则,我将在几天后将其设置为答案。