我已经实现了一个自定义的并发可观察集合,可以使用一个简单的锁针对所有 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)));
}
注意:_context
是Application.Current.Dispatcher
。
现在我发现了BindingOperations.EnableCollectionSynchronization
,并且-据我了解的文档-它在锁定方面无济于事,而仅在正确调用CollectionChanged
事件方面。
对吗?我应该使用BindingOperations.EnableCollectionSynchronization
吗?会有什么不同?
答案 0 :(得分:0)
如果您计划对数据进行主动修改,我的建议是请勿使用BindingOperations.EnableCollectionSynchronization
。
我在一个项目中大量使用了该项目,在该项目中,大数据集被分块加载到单独的线程中。加载块后,在启用ObservableCollection
的情况下将数据泵入BindingOperations.EnableCollectionSynchronization
。用户也可能取消操作并开始新的数据加载。在这种情况下,我们清除了“ ObservableCollection”并再次从另一个线程重新填充它。
结果是不时发生崩溃。我们将崩溃跟踪到ListCollectionView
类的代码中,该类包含允许多线程访问的锁定。它有一个细微的错误,我无法报告,因为我无法创建100%可复制的样本。
我们所做的是通过ObservableCollection
从UI线程重定向填充Dispatcher.BeginInvoke
。
更好地实现自己的同步,您将能够测试并最终修复代码。