在我的程序中,我有一个抽象类ObservableKeyedCollection<TKey, TItem>
,它继承自KeyedCollection<TKey, TItem>
并实现了INotifyCollectionChanged
。
此抽象类的实现绑定(bind)到ListBox
。在此ListBox
中,我双击编辑项目,并在接受后从此ObservableKeyedCollection<TKey, TItem>
实现中删除已编辑项目的旧实例,并添加已修改的新实例。
在Windows 10 Creators Update(1703,内部版本号15063.250)之前,这一切都运行良好。从更新开始,ObservableKeyedCollection<TKey, TItem>
开始抛出InvalidOperationException
,并显示以下消息:
我不在代码的此区域中使用任何异步操作。
整个堆栈跟踪将太长,但这是从OnCollectionChanged
开头的顶部:
编辑1:
这是有问题的代码部分,在Creators Update(覆盖KeyedCollection<TKey, TItem>.RemoveItem(int index)
)之前可以正常工作:
protected override void RemoveItem(int index)
{
TItem item = this[index];
base.RemoveItem(index);
if (deferNotifyCollectionChanged) return;
if (item is IList) {
// Listeners do not support multiple item changes, and our item happens to be an IList, so we must raise NotifyCollectionChangedAction.Reset.
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
} else {
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
}
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
}
仅当我使用
OnCollectionChanged
操作调用NotifyCollectionChangedAction.Remove
时,才会出现该问题。用NotifyCollectionChangedAction.Reset
替换它似乎可以避免出现异常:protected override void RemoveItem(int index)
{
TItem item = this[index];
base.RemoveItem(index);
if (deferNotifyCollectionChanged) return;
// No exception thrown so far if I stick to NotifyCollectionChangedAction.Reset:
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
}
我尝试使用
Dispatcher
解决此问题,如下所示:https://stackoverflow.com/a/22026686/2659699,尽管我的调度程序不为null,但其CheckAccess()
的计算结果为true,并且在NotifyCollectionChangedEventHandler.Invoke()
上仍然收到相同的异常。非常感谢您的想法和协助。
最佳答案
Win 10创建者更新后,我也遇到了类似的问题。
这个使用BindingOperations.EnableCollectionSynchronization的包装类为我工作:
public class SynchronizedObservableCollection<T> : ObservableCollection<T>
{
private readonly object _lockObject = new object();
public SynchronizedObservableCollection()
{
Init();
}
public SynchronizedObservableCollection(List<T> list) : base(list)
{
Init();
}
public SynchronizedObservableCollection(IEnumerable<T> collection) : base(collection)
{
Init();
}
private void Init()
{
BindingOperations.EnableCollectionSynchronization(this, _lockObject);
}
}
关于c# - 创建者更新后,在OnCollectionChanged上获取线程访问异常,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43833117/