我正在尝试在AsyncObservableCollection
上实现RemoveAll
,这个类是为在另一个线程上编辑集合而创建的,结构是这样的:
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
private readonly SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
public AsyncObservableCollection()
{
}
public AsyncObservableCollection(IEnumerable<T> list)
: base(list)
{
}
private void ExecuteOnSyncContext(Action action)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
action();
}
else
{
_synchronizationContext.Send(_ => action(), null);
}
}
protected override void InsertItem(int index, T item)
{
ExecuteOnSyncContext(() => base.InsertItem(index, item));
}
protected override void RemoveItem(int index)
{
ExecuteOnSyncContext(() => base.RemoveItem(index));
}
protected override void SetItem(int index, T item)
{
ExecuteOnSyncContext(() => base.SetItem(index, item));
}
protected override void MoveItem(int oldIndex, int newIndex)
{
ExecuteOnSyncContext(() => base.MoveItem(oldIndex, newIndex));
}
protected override void ClearItems()
{
ExecuteOnSyncContext(() => base.ClearItems());
}
public void RemoveAll(Predicate<T> predicate)
{
CheckReentrancy();
List<T> itemsToRemove = Items.Where(x => predicate(x)).ToList();
itemsToRemove.ForEach(item => Items.Remove(item));
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
实际上,如果在主线程上使用该集合,该方法运行良好,但如果我在不同的线程上使用,我会得到:
Not Supported Exception
在这一行:
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
我可以做些什么来解决这个问题?
最佳答案
我不太确定这个类的目的以及为什么你需要保持当前上下文,但无论如何你的问题的解决方案是
public class ObservableCollectionAsync<T> : ObservableCollection<T>
{
public ObservableCollectionAsync()
{
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
public ObservableCollectionAsync(List<T> list) : base(list)
{
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
public ObservableCollectionAsync(IEnumerable<T> collection) : base(collection)
{
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
private readonly SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
private readonly object _lock = new object();
private void ExecuteOnSyncContext(Action action)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
action();
}
else
{
_synchronizationContext.Send(_ => action(), null);
}
}
protected override void ClearItems()
{
ExecuteOnSyncContext(() => base.ClearItems());
}
protected override void InsertItem(int index, T item)
{
ExecuteOnSyncContext(() => base.InsertItem(index, item));
}
protected override void MoveItem(int oldIndex, int newIndex)
{
ExecuteOnSyncContext(() => base.MoveItem(oldIndex, newIndex));
}
protected override void RemoveItem(int index)
{
ExecuteOnSyncContext(() => base.RemoveItem(index));
}
protected override void SetItem(int index, T item)
{
ExecuteOnSyncContext(() => base.SetItem(index, item));
}
public void RemoveAll(Func<T,bool> predicate)
{
CheckReentrancy();
foreach (var item in this.Where(predicate).ToArray())
{
this.Remove(item);
}
}
但是 Observable Collection 本身中的任何其他方法都不会通过您的“ExecuteOnSyncContext”,因此最好将其公开并在类外部为其他方法调用它。
否则,您将需要使用 ICollection 接口(interface)构建一个 Observable 集合。
关于c# - 在 AsyncObservableCollection 上实现 RemoveAll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47287326/