C# 使用WPF MVVM Light DispatcherHelper
我有一个WPF应用程序,其中一些控件属性绑定到相对viewmodel中的属性 以下是相关的XAML代码:C# 使用WPF MVVM Light DispatcherHelper,c#,wpf,multithreading,data-binding,mvvm-light,C#,Wpf,Multithreading,Data Binding,Mvvm Light,我有一个WPF应用程序,其中一些控件属性绑定到相对viewmodel中的属性 以下是相关的XAML代码: [..] <StackPanel> <Ellipse Width="20" Height="20" Fill="{Binding ServiceStatus.Colore}"/> <TextBlock Text="{Binding ServiceStatus.Stato}" FontSize="8"></TextBlock> &
[..]
<StackPanel>
<Ellipse Width="20" Height="20" Fill="{Binding ServiceStatus.Colore}"/>
<TextBlock Text="{Binding ServiceStatus.Stato}" FontSize="8"></TextBlock>
</StackPanel>
[..]
这是ViewModel:
public class MainViewModel : ViewModelBase
{
private StatusDTO _ServiceStatus;
public StatusDTO ServiceStatus
{
get { return _ServiceStatus; }
set { _ServiceStatus = value; }
}
public MainViewModel()
{
[...]
_ServiceStatus = new StatusDTO();
_ServiceStatus.ServiceStatus = SS_UNKNOWN;
_ServiceStatus.Stato = "INITIALIZING...";
_ServiceStatus.Colore = new SolidColorBrush(Colors.Gray);
CheckServiceStatus();
[...]
}
private void CheckServiceStatus()
{
ThreadPool.QueueUserWorkItem(o =>
{
Service.StatoServizio ss = SS_UNKNOWN;
while (true)
{
Thread.Sleep(5000);
ss = Service.ServiceManager.GetServiceStatus();
if (_ServiceStatus.ServiceStatus == ss)
continue;
_ServiceStatus.ServiceStatus = ss;
switch (_ServiceStatus.ServiceStatus)
{
case SS_STOPPED:
_ServiceStatus.Stato = "STOPPED";
_ServiceStatus.Colore = new SolidColorBrush(Colors.Red);
break;
[...]
}
DispatcherHelper.CheckBeginInvokeOnUI(() => { RaisePropertyChanged("ServiceStatus"); }); <----- HERE I GOT THE EXCEPTION
}
});
}
如果我像在viewmodel的构造函数中一样更新UI线程中的_ServiceStatus,则UI将得到更新
我的问题是:DispatcherHelper.CheckBeginInvokeOnUI不是为了避免这个问题吗?我做错了什么?
谢谢大家! 您应该在UI线程上创建颜色笔刷,或者在后台线程上调用其冻结方法:
case SS_STOPPED:
_ServiceStatus.Stato = "STOPPED";
_ServiceStatus.Colore = new SolidColorBrush(Colors.Red);
_ServiceStatus.Colore.Freeze(); // <--
break;
您应该能够从后台线程调用RaisePropertyChanged方法,而无需使用DispatcherHelper.CheckBeginInvokeOnUI方法。已尝试过,但结果是相同的例外笔刷可能是您的问题。请参考我的答案。请注意,如果您在视图模型中创建笔刷,可能是做错了什么。视图模型应该很少注意颜色、画笔、可见性等。如果您感兴趣,欢迎加入。我们专注于使用MVVM的WPF,并且通常在大多数工作日使用。是的,冻结解决了问题,但没有选中BeginInVokeOnUI。我的意思是通过在主UI线程中执行RaisePropertyChanged来避免使用冻结?否。在这种情况下,它只是在UI线程上调用委托RaisePropertyChanged。它不会冻结交叉线程访问的刷子。正如我在第一条评论中提到的,您不需要在UI线程上调用RaisePropertyChanged。但据我所知,我对整个mvvm&wpf都是新手,只要在主线程上更新属性,就不需要冻结属性。我错了吗?是的,如果您在后台线程上创建了一个可冻结的文件,例如画笔,那么您必须显式冻结它,以便能够在另一个线程(例如UI线程)上使用它。
Must create DependencySource on same Thread as the DependencyObject
case SS_STOPPED:
_ServiceStatus.Stato = "STOPPED";
_ServiceStatus.Colore = new SolidColorBrush(Colors.Red);
_ServiceStatus.Colore.Freeze(); // <--
break;