在我的程序中,我有一个抽象类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/

10-12 01:25