Getting thread access exceptions in OnCollectionChanged after updating for authors

In my program, I have an abstract class ObservableKeyedCollection<TKey, TItem>that inherits from KeyedCollection<TKey, TItem>, and also implements INotifyCollectionChanged.

The implementation of this abstract class is related to a ListBox. In this, ListBoxI edit the elements with a double click, and after accepting, it removes the old instance of the edited element from this implementation ObservableKeyedCollection<TKey, TItem>and adds a new instance that has been modified.

Everything worked well until the Windows 10 Creators Update (1703, build number 15063.250). Starting with the update, I ObservableKeyedCollection<TKey, TItem>started throwing InvalidOperationExceptionwith the following message:

The calling thread cannot access this object because another thread belongs to it.

I do not use any asynchronous operations in this area of ​​code.

The whole stack trace will be too long, but the top part starts with OnCollectionChanged:

in System.Windows.Threading.Dispatcher.VerifyAccess () in System.Windows.Threading.DispatcherObject.VerifyAccess () in System.Windows.DependencyObject.GetValue (DependencyProperty dp) in System.Windows.Controls.Primitives.Selector.GetIselect DependencyObject) in System.Windows.Controls.Primitives.Selector.ItemSetIsSelected (ItemInfo information, boolean) in System.Windows.Controls.Primitives.Selector.SelectionChanger.CreateDeltaSelectionChange (List'1 unselectedItems, List'1 selectedIItems) .Controls.Primitives.Selector.SelectionChanger.End () in System.Windows.Controls.Primitives.Selector.RemoveFromSelection (NotifyCollectionChangedEventArgs e) in System.Windows.Controls.Primitives.Selector.OnItemsChanged (NotifyCollectionChanged) .ItemsControl.OnItemCollectionChanged2 (sender of the object, NotifyCollectionChangedEventArgs e) in System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke (sender of the object, NotifyCollectionChangedEventArgs e) in System.Windows.Data.CollectionView.OnColColCollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionChollectionCholChollectionChollectionChollectionChollectionChollectionCholChollectionChollectionChollectionChollectionChollectionCholCholCholCholCholCholCholCholColColCholColChollectioncolgolqolqollectionCholChollectionChollectionChollectionCholColChollectionCholcolgolgolgolgolgolgolgolgolgolgolgolgolqolqollection sender of the object, NotifyCollectionChangedEventArgs e) in System.Windows.WeakEventManager.ListenerList'1.DeliverEvent (sender of the object, EventArgs e, type typeType) in System.Windows.WeakEventManager.DeliverEventToList (sender of the object, arguments to EventArgs, List ofenerener .WeakEventManager.DeliverEvent (object sender, EventArgs arguments) in System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged (Object sender, NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndexdecldelddecldecldecldecldecldecldeqdeqldq .ProcessCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged (Sender Object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanggs \ ObservableKeyedCollection.cs, line number: 68 in TetheredSun.ObservableKeyedCollection`2.RemoveItem (index Int32) in [...]]]NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustOldIndex, Int32 adjustNewIndex) in System.Windows.Data.ListCollectionView.ProcessCollectionChanged (NotifyCollectionChangedEventArgs args ) in System.Windows.Data.CollectionView.OnCollectionChanged (Sender object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Program \ oz Tethered Obs Obs Obs Obs Obs ok ok Obs Obs ok Obs Obs Obs Obs Obs Obs Obs Obs Obs Obs line number: 68 in TetheredSun.ObservableKeyedCollection`2.RemoveItem (Int32 index) in [...]NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustOldIndex, Int32 adjustNewIndex) in System.Windows.Data.ListCollectionView.ProcessCollectionChanged (NotifyCollectionChangedEventArgs args ) in System.Windows.Data.CollectionView.OnCollectionChanged (Sender object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Program \ oz Tethered Obs Obs Obs Obs Obs ok ok Obs Obs ok Obs Obs Obs Obs Obs Obs Obs Obs Obs Obs line number: 68 in TetheredSun.ObservableKeyedCollection`2.RemoveItem (Int32 index) in [...]Windows.Data.CollectionView.OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustColdChollection.OldChollection.OldChollection.OldChollection.OldChollection.OldChollection.OldChol.X.ChangeX.a. Data.CollectionView.OnCollectionChanged (Sender Object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ Modulok \ TetheredSunun.1 String Tunsunun.1 .ObservableKeyedCollection`2.RemoveItem (index Int32) in [...]Windows.Data.CollectionView.OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustColdChollection.OldChollection.OldChollection.OldChollection.OldChollection.OldChollection.OldChol.X.ChangeX.a. Data.CollectionView.OnCollectionChanged (Sender Object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ Modulok \ TetheredSunun.1 String Tunsunun.1 .ObservableKeyedCollection`2.RemoveItem (index Int32) in [...]OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustOldIndex, Int32 adjustNewIndex) in System.Windows.Data.ListCollectionView.ProcessCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged ( The sender object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ Modulok \ TetheredSun.1emIedCemableTeySemableTeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeyed (index Int32) in [...]OnCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustOldIndex, Int32 adjustNewIndex) in System.Windows.Data.ListCollectionView.ProcessCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged ( The sender object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ Modulok \ TetheredSun.1emIedCemableTeySemableTeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeySedableIeyCemableTeyed (index Int32) in [...]ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustOldIndex, Int32 adjustNewIndex) in System.Windows.Data.ListCollectionView.ProcessCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged (object sender, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ Modulok \ TetheredSun.1.0 \ TetheredSun \ ObservableKeyedCollection.cs, line number: 68 in TetheredSun.ObservableKeyedCollection`2.RemoveItem (index Int32) in [...]ProcessCollectionChangedWithAdjustedIndex (NotifyCollectionChangedEventArgs args, Int32 adjustOldIndex, Int32 adjustNewIndex) in System.Windows.Data.ListCollectionView.ProcessCollectionChanged (NotifyCollectionChangedEventArgs args) in System.Windows.Data.CollectionView.OnCollectionChanged (object sender, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ Modulok \ TetheredSun.1.0 \ TetheredSun \ ObservableKeyedCollection.cs, line number: 68 in TetheredSun.ObservableKeyedCollection`2.RemoveItem (index Int32) in [...]OnCollectionChanged (Sender object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ ModulCentableTedKeySuncedunun string .RemoveItem (Int32 index) in [...]OnCollectionChanged (Sender object, NotifyCollectionChangedEventArgs args) in TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged (NotifyCollectionChangedEventArgs e) in e: \ Phil \ Programozás \ ModulCentableTedKeySuncedunun string .RemoveItem (Int32 index) in [...]

1:

, ( 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, : qaru.site/questions/85800/..., , CheckAccess() true, NotifyCollectionChangedEventHandler.Invoke().

.

+4
1

, 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);
    }
}
+1

Source: https://habr.com/ru/post/1676602/


All Articles