为什么要使用BindingOperations.EnableCollectionSynchronization?

时间:2019-01-17 09:47:04

标签: c# wpf concurrency binding

我已经实现了一个自定义的并发可观察集合,可以使用一个简单的锁针对所有 write 操作和一个数组快照(在锁内部每次更改时创建),可以从多个线程中对其进行修改。用于所有 read 操作。 (请参见https://codereview.stackexchange.com/questions/210575/concurrent-observable-collection以获得稍为过时的版本,以了解其想法。)

根据WPF在实现INotifyCollectionChanged时的要求,我在调度程序的线程上调用CollectionChanged事件,如下所示:

private void _notify(NotifyCollectionChangedEventArgs args)
{
    if (_context == null)
    {
        _invokeCollectionChanged(args);
    }
    else if (_context.CheckAccess())
    {
        _invokeCollectionChanged(args);
    }
    else
    {
        _context.InvokeAsync(() => _invokeCollectionChanged(args));
    }
}

private void _invokeCollectionChanged(NotifyCollectionChangedEventArgs args)
{
    CollectionChanged?.Invoke(this, args);

    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
}

注意:_contextApplication.Current.Dispatcher

现在我发现了BindingOperations.EnableCollectionSynchronization,并且-据我了解的文档-它在锁定方面无济于事,而仅在正确调用CollectionChanged事件方面。

对吗?我应该使用BindingOperations.EnableCollectionSynchronization吗?会有什么不同?

1 个答案:

答案 0 :(得分:0)

如果您计划对数据进行主动修改,我的建议是请勿使用BindingOperations.EnableCollectionSynchronization

我在一个项目中大量使用了该项目,在该项目中,大数据集被分块加载到单独的线程中。加载块后,在启用ObservableCollection的情况下将数据泵入BindingOperations.EnableCollectionSynchronization。用户也可能取消操作并开始新的数据加载。在这种情况下,我们清除了“ ObservableCollection”并再次从另一个线程重新填充它。

结果是不时发生崩溃。我们将崩溃跟踪到ListCollectionView类的代码中,该类包含允许多线程访问的锁定。它有一个细微的错误,我无法报告,因为我无法创建100%可复制的样本。

我们所做的是通过ObservableCollection从UI线程重定向填充Dispatcher.BeginInvoke

更好地实现自己的同步,您将能够测试并最终修复代码。