gpt4 book ai didi

c# - Creators Update 后在 OnCollectionChanged 上获取线程访问异常

转载 作者:太空狗 更新时间:2023-10-29 23:43:31 36 4
gpt4 key购买 nike

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

此抽象类的实现绑定(bind)到 ListBox .在这个ListBox ,我双击编辑项目,并在接受后,从这个 ObservableKeyedCollection<TKey, TItem> 中删除编辑项目的旧实例实现,并添加修改后的新实​​例。

在 Windows 10 Creators Update(1703,内部版本号 15063.250)之前一切正常。自更新以来,ObservableKeyedCollection<TKey, TItem>开始 throw InvalidOperationException带有以下消息:

The calling thread cannot access this object because a different thread owns it.

我没有在代码的这个区域使用任何异步操作。

整个堆栈跟踪会太长,但这里是顶部以 OnCollectionChanged 开头的部分:

at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Threading.DispatcherObject.VerifyAccess() at System.Windows.DependencyObject.GetValue(DependencyProperty dp) at System.Windows.Controls.Primitives.Selector.GetIsSelected(DependencyObject element) at System.Windows.Controls.Primitives.Selector.ItemSetIsSelected(ItemInfo info, Boolean value) at System.Windows.Controls.Primitives.Selector.SelectionChanger.CreateDeltaSelectionChange(List'1 unselectedItems, List'1 selectedItems) at System.Windows.Controls.Primitives.Selector.SelectionChanger.End() at System.Windows.Controls.Primitives.Selector.RemoveFromSelection(NotifyCollectionChangedEventArgs e) at System.Windows.Controls.Primitives.Selector.OnItemsChanged(NotifyCollectionChangedEventArgs e) at System.Windows.Controls.ItemsControl.OnItemCollectionChanged2(Object sender, NotifyCollectionChangedEventArgs e) at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e) at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) at System.Windows.Controls.ItemCollection.OnViewCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) at System.Windows.WeakEventManager.ListenerList'1.DeliverEvent(Object sender, EventArgs e, Type managerType) at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) at System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex(NotifyCollectionChangedEventArgs args, Int32 adjustedOldIndex, Int32 adjustedNewIndex) at System.Windows.Data.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args) at System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) at TetheredSun.ObservableKeyedCollection'2.OnCollectionChanged(NotifyCollectionChangedEventArgs e) at e:\Phil\Programozás\Modulok\TetheredSun.1.0\TetheredSun\ObservableKeyedCollection.cs, line number: 68 at TetheredSun.ObservableKeyedCollection`2.RemoveItem(Int32 index) at [...]

编辑 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 解决问题如此处所示:https://stackoverflow.com/a/22026686/2659699但是虽然我的调度员不为空,但它是 CheckAccess()计算结果为真,我在 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# - Creators Update 后在 OnCollectionChanged 上获取线程访问异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43833117/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com