SortableBindingList,索引超出范围错误,如何使其线程安全

本文关键字:何使其 安全 错误 线程 范围 索引 SortableBindingList | 更新日期: 2023-09-27 18:01:08

using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace MyApplication
{
    public class SortableBindingList<T> : BindingList<T>
    {
        private static object syncLock = new object();
        private readonly Dictionary<Type, PropertyComparer<T>> comparers;
        private bool isSorted;
        private ListSortDirection listSortDirection;
        private PropertyDescriptor propertyDescriptor;
        private System.ComponentModel.ISynchronizeInvoke _SyncObject;
        private System.Action<System.ComponentModel.ListChangedEventArgs> _FireEventAction;
        public SortableBindingList()
            : base(new List<T>())
        {
            this.comparers = new Dictionary<Type, PropertyComparer<T>>();
        }
        public SortableBindingList(IEnumerable<T> enumeration, System.ComponentModel.ISynchronizeInvoke syncObject)
            : base(new List<T>(enumeration))
        {
            _SyncObject = syncObject;
            _FireEventAction = FireEvent;
            this.comparers = new Dictionary<Type, PropertyComparer<T>>();
        }
        protected override bool SupportsSortingCore
        {
            get { return true; }
        }
        protected override bool IsSortedCore
        {
            get { return this.isSorted; }
        }
        protected override PropertyDescriptor SortPropertyCore
        {
            get { return this.propertyDescriptor; }
        }
        protected override ListSortDirection SortDirectionCore
        {
            get { return this.listSortDirection; }
        }
        protected override bool SupportsSearchingCore
        {
            get { return true; }
        }
        protected override void InsertItem(int index, T item)
        {
            lock (syncLock)
            {
                base.InsertItem(index, item);
            }
        }
        protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
        {
            List<T> itemsList = (List<T>)this.Items;
            Type propertyType = property.PropertyType;
            PropertyComparer<T> comparer;
            if (!this.comparers.TryGetValue(propertyType, out comparer))
            {
                comparer = new PropertyComparer<T>(property, direction);
                this.comparers.Add(propertyType, comparer);
            }
            comparer.SetPropertyAndDirection(property, direction);
            itemsList.Sort(comparer);
            this.propertyDescriptor = property;
            this.listSortDirection = direction;
            this.isSorted = true;
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
        protected override void RemoveSortCore()
        {
            this.isSorted = false;
            this.propertyDescriptor = base.SortPropertyCore;
            this.listSortDirection = base.SortDirectionCore;
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
        protected override int FindCore(PropertyDescriptor property, object key)
        {
            int count = this.Count;
            for (int i = 0; i < count; ++i)
            {
                T element = this[i];
                if (property.GetValue(element).Equals(key))
                {
                    return i;
                }
            }
            return -1;
        }
        protected override void OnListChanged(System.ComponentModel.ListChangedEventArgs args)
        {
            lock (syncLock)
            {
                if (_SyncObject == null)
                {
                    FireEvent(args);
                }
                else
                {
                    _SyncObject.Invoke(_FireEventAction, new object[] { args });
                }
            }
        }
        private void FireEvent(System.ComponentModel.ListChangedEventArgs args)
        {
            base.OnListChanged(args);
        }
    }
}

我得到以下错误:

指数超出范围。必须是非负数并且小于集合的大小。参数名称:index

  1. SortableBindingList绑定到DataGridView,虚拟模式
  2. 多个线程触发将数据添加到SortableBindingList的事件

private void ProxyScraper_OnProxyFound(Proxy Proxy, int Count)
{       
    ProxyProcessedCount.Text = Count.ToString();
    _ProxyList.Add(Proxy);
}

我试图锁定SortableBindingList,但仍然出现错误,搜索了很多,但找不到解决方案。

SortableBindingList,索引超出范围错误,如何使其线程安全

最终,我怀疑制作一个真正线程安全的绑定列表是错误的,因为在某些情况下会执行多个操作——无论是"检查计数,然后将行迭代到计数-1"还是"使用foreach枚举"——而且没有简单的方法来锁定这些操作的持续时间,因为调用代码超出了您的控制范围。

即使是半工作版本,您也需要通过覆盖所有可用方法,将syncLock代码添加到每次访问中-然而,我在this[index]上看不到get的虚拟方法,这可能会使无效-只有当所有调用方都同意使用锁时,它才会同步。

最终,我怀疑尝试使用具有紧密UI耦合的线程是注定要失败的。IMO,您可能会更成功地将这两件事分开,并让UI担心处理事件和调用.Invoke(...)来更新UI线程上的绑定。