在创建者更新后,在OnCollectionChanged上获得线程访问例外



在我的程序中,我有一个从 KeyedCollection<TKey, TItem>继承的抽象类ObservableKeyedCollection<TKey, TItem>,并且也实现了INotifyCollectionChanged

实现此抽象类的实现与ListBox绑定。在此ListBox中,我在双击时编辑项目,并在接受后,从此ObservableKeyedCollection<TKey, TItem>实现中删除已编辑项目的旧实例,然后添加已修改的新实例。

Windows 10创建者更新(1703,构建编号15063.250(之前,一切都很好。自更新以来,ObservableKeyedCollection<TKey, TItem>开始使用以下消息扔InvalidOperationException s:

呼叫线程无法访问此对象,因为一个不同的线程拥有它。

我在代码的此区域中不使用任何异步操作。

整个堆栈跟踪的时间太长,但这是从OnCollectionChanged开始的最高部分:

在system.windows.threading.dispatcher.verifyAccess(( 在System.Windows.threading.dispatcherobject.verifyAccess(( 在system.windows.dependendencyObject.getValue(depentencyProperty dp( 在System.windows.controls.primitives.selector.getisselected(dependencyObject element(上 在System.Windows.Controls.Primitives.Selector.ItemSetisseledectectect(ItemInfo Info,boolean value( at System.windows.controls.primitives.selector.selection Changer.createdEdeltaselectionChange(list'1 unsectectionEms,list'1 selectedItems( 在system.windows.controls.primitives.selector.selection Changer.end(( 在system.windows.controls.primitives.selector.removefromselection(notifyCollectionChangeDeventargs e( 在system.windows.controls.primitives.selector.onitemschanged上 在system.windows.controls.itemscontrol.onitemcollectionChanged2(对象发送者,notifyCollectionChangeDeventargs e(上 在system.collections.specialized.notifyCollectionChangedEventHandler.Invoke(对象发送者,notifyCollectionChangeDeventargs e( 在System.Windows.Data.CollectionView.OnCollectionChanged(notifyCollectionChangeDeventargs args( 在system.windows.controls.itemcollection.onviewCollectionChanged(对象发送者,notifyCollectionChangeDeventargs e( 在system.windows.weakeventmanager.listenerlist'1.deliverevent(对象发送者,EventArgs E,type ManagerType( 在system.windows.weakeventmanager.delivereventtolist(对象发送者,EventArgs args,ListorerList列表( 在system.windows.weakeventmanager.deliverevent(对象发送者,EventArgs args( at System.Collections.specialized.CollectionChangeDeventManager.OnCollectionChanged(对象发送者,notifyCollectionChangeDeventargs args( 在System.Windows.Data.CollectionView.OnCollectionChanged(notifyCollectionChangeDeventargs args( at System.Windows.Data.listCollectionView.ProcessCollectionChangedChangedWithAdjustedIndex(notifyCollectionChangeDeventArgs args,INT32 AdjustedEddIndex,Int32 AdjustedNewIndex( 在System.Windows.Data.listCollectionView.ProcessCollectionChanged(notifyCollectionChangeDeventargs args( 在System.Windows.Data.CollectionView.OnCollectionChanged(对象发送者,notifyCollectionChangeDeventargs args( 在tetheredsun.ObservableKeyedCollection'2.OnCollectionChanged(notifyCollectionChangeDeventargs e(e: 在tetheredsun.observablekeyedCollection`2.RemoveItem(int32 index(at [...]

编辑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"));
}

问题似乎只有在我用NotifyCollectionChangedAction.Remove操作调用OnCollectionChanged时就会发生。用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/a/22026686/2659699,但是尽管我的调度员并非无效,但它的CheckAccess()还是不断评估的,我一直保持相同的状态NotifyCollectionChangedEventHandler.Invoke()

的例外

非常感谢您的想法和帮助。

我也有类似的问题,也有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);
    }
}

最新更新