WPF绑定到并发集合是否安全?

时间:2018-11-24 23:48:16

标签: wpf multithreading data-binding concurrent-collections

我想知道,是否可以安全地将WPF控件绑定到并发集合,特别是围绕同时实现System.Collections.Concurrent的{​​{1}}集合之一的包装类?

我了解到INotifyCollectionChanged必须在UI线程上被调用(并且没有索引参数)。但是,如果在UI更新自身时另一个线程操纵了源集合,会发生什么? WPF是否会优雅地忽略该问题(就像在许多其他地方一样)?

1 个答案:

答案 0 :(得分:1)

这取决于包装程序的实现。让我们做一个简单的示例,将INotifyCollectionChanged添加到BlockingCollection<T>,以允许调用非UI线程:

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根据NotifyCollectionChangedAction更新UI,并更新在提高INotifyCollectionChanged.CollectionChanged时传递的项目。这意味着UI依赖于此信息。结果:临时集合更新导致UI保持不同步,直到引发更新或调用NotifyCollectionChangedAction.Reset且该UI显示诸如源集合内部之类的不同项为止。

通过UI同步集合是一个非常广泛且引人入胜的话题。已经有多种解决方案可以匹配您的特定问题。为了给您提供解决此类问题的可能方法,请看以下一些链接: