c# - 在 AsyncObservableCollection 上实现 RemoveAll

标签 c# multithreading

我正在尝试在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/

相关文章:

c# - 在构建所有内容之前不刷新 XNA 内容构建输出

java - JNI - Java 在 native 线程完成执行之前退出

c++ - 非静态数据成员的 thread_local 数据,再一次

java - Java中使用线程并发模拟多核CPU

c++ - 互斥锁映射c++11

c++ - 持续更新 GUI 表单元素,使 Form 不挂起

c# - C#中旋转的RectangleGeometry的左上角点

c# - 确定堆上对象的对象分配发生的位置

c# - WCF CustomBinding - 无法使用自定义授权策略获取元数据

c# - epplus公式错误