2015-10-19 60 views
1

随着INotifyPropertyChanged的实现,我经常遇到典型的多线程异常:“调用线程无法访问此对象,因为不同的线程拥有它。”为了解决这个问题,我决定尝试和执行一个线程安全的OnPropertyChanged方法如下:INotifyPropertyChanged:使用线程安全分派器实现的风险

[field: NonSerialized] 
    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 

     Application.Current.Dispatcher.Invoke(new Action(() => 
     { 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(name)); 
      } 
     }));       
    } 

我已经指出的那样,是有一个显著性能降低。除此之外,实施这种方法还有其他风险/顾虑吗?

编辑

我使用WPF GUI技术。

回答

4

您应该检查,如果你是在UI线程首先避免uneccessary调度:

Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread); 
if (dispatcher != null) // already on UI thread, no dispatching needed 
{ 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
} 
else 
{ 
    Application.Current.Dispatcher.Invoke(new Action(() => 
    { 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    })); 
} 

上面的代码中可能需要改变,因为你没有指定使用哪个GUI技术,但你的想法。

但如果你问我,你应该选择不同的方法一起,做调度,当你修改的属性:

Application.Current.Dispatcher.Invoke(new Action(() => 
    MyViewModel.MyProperty = "X"); 
+0

好,谢谢,使有很大的意义。为什么你特别喜欢第一个选项?我在应用程序中有大量的视图模型,并希望在一个地方包含所有INotifyPropertyChanged&Dispatcher逻辑,这样我就不必去查找所有有问题的属性(并使用第二种方法设置它们)。 –

+0

IMO的自动调度可能会隐藏可能没有调度程序的有问题的代码,您应该知道在UI线程上运行的是什么,而哪些没有。线程错误很难找到,所以我更喜欢明确的方法。但取决于您的应用程序,它可能没有问题。 – thumbmunkeys