我想知道,将WPF控件绑定到并发集合,特别是围绕一个也实现INotifyCollectionChanged
的System.Collections.Concurrent
集合的包装类,是否安全?
我知道CollectionChanged
必须在UI线程上调用(并且没有索引参数(。但是,如果另一个线程在UI更新自身的同时操纵源集合,会发生什么呢?WPF是否只是优雅地忽略了这个问题(就像在许多其他地方一样(?
这取决于包装器的实现。让我们举一个简单的例子,将INotifyCollectionChanged
添加到允许调用非UI线程的BlockingCollection<T>
中:
public void AddNotified(T item)
{
base.Add(item);
var args = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
item,
Count - 1);
//Ensure no items are changed until the UI is updated
Application.Current.Dispatcher.Invoke(() =>
CollectionChanged?.Invoke(this, args));
}
Add
的实现本身是线程安全的,但为了确保UI显示当前项,您需要确保在添加和更新之间没有其他项发生更改(请参阅代码中的注释(。
WPF基于CCD_ 7和在引发CCD_。这意味着UI依赖于这些信息。结果是:临时集合更新会导致一个不同步的UI,直到引发更新或调用NotifyCollectionChangedAction.Reset
,并且UI显示不同的项目,如源集合中的项目。
将集合与UI同步是一个非常广泛和有趣的话题。已经有多种解决方案可以满足您的特定问题。为了给你一些可能的方法来解决这样的问题,看看这里有一些链接:
- .NET 4中是否存在Threadsafe Observable集合
- Threadsafe ObservableCollection
BindingOperations.EnableCollectionSynchronization