C# 使用WPF MVVM Light DispatcherHelper

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> &

我有一个WPF应用程序,其中一些控件属性绑定到相对viewmodel中的属性

以下是相关的XAML代码:

[..]
<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;