【发布时间】:2013-10-11 14:33:17
【问题描述】:
我正在开发一个 WPF 应用程序,发现绑定属性的属性更改通知可以从后台线程发生,但是对于 observablecollection 的任何更改(如添加或删除项目)必须从 UI 线程发生。我的问题是为什么会这样? INotifyPropertyChanged 和 INotifyCollectionChanged 都是由 UI 控件订阅的,那为什么 INotifyPropertyChanged 会例外?
例如:
public class ViewModel : INotifyPropertyChanged
{
ObservableCollection<Item> _items = new ObservableCollection<Item>();
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
//Can fire this from a background thread without any crash and my
//Name gets updated in the UI
InvokePropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
public void Add(Item item)
{
//Cant do this from a background thread and has to marshal.
_items.Add(item);
}
public event PropertyChangedEventHandler PropertyChanged;
public void InvokePropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, e);
}
}
注意:来自后台线程的 CollectionChanged 事件使应用程序崩溃,但是来自后台线程的 PropertyChanged 事件更新 UI 没有任何问题,是的,这是在 .NET 4.0 中
【问题讨论】:
-
ObservableCollection 不是线程安全的类,很少有集合类是。不需要在 UI 线程上进行任何更改。但是,如果您在修改 UI 的类中侦听 PropertyChanged 事件,那么它肯定会开始变得重要。这与集合类没有任何关系,与您的事件处理程序代码所做的一切有关。
-
@Hans:确切地说,通知属性已更改和通知集合已更改均由 UI 控件(如网格)订阅。为什么它允许从后台线程(无需编组)引发标量属性的属性更改通知,但 NotifyCollectionChanged 只能从 UI 线程?
标签: c# wpf multithreading