INotifyPropertyChanged:线程安全 Dispatcher 实现的风险
INotifyPropertyChanged: Risks with thread-safe Dispatcher implementation
随着 INotifyPropertyChanged 的实现,我经常遇到典型的多线程异常:"The calling thread cannot access this object because a different thread owns it."为了解决这个问题,我决定尝试实现一个线程安全的 OnPropertyChanged 方法,如下所示:
[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));
}
}));
}
我注意到,存在显着的性能压力。除此之外,是否还有其他 risks/concerns 实施此方法?
编辑
我正在使用 WPF GUI 技术。
您应该首先检查您是否在 UI 线程上以避免不必要的调度:
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");
随着 INotifyPropertyChanged 的实现,我经常遇到典型的多线程异常:"The calling thread cannot access this object because a different thread owns it."为了解决这个问题,我决定尝试实现一个线程安全的 OnPropertyChanged 方法,如下所示:
[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));
}
}));
}
我注意到,存在显着的性能压力。除此之外,是否还有其他 risks/concerns 实施此方法?
编辑
我正在使用 WPF GUI 技术。
您应该首先检查您是否在 UI 线程上以避免不必要的调度:
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");