简体   繁体   English

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

[英]SortableBindingList, Index was out of range Error, how to make it Thread-Safe?

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);
        }
    }
}

I am getting following error:我收到以下错误:

Index was out of range.指数超出范围。 Must be non-negative and less than the size of the collection.必须是非负数且小于集合的大小。 Parameter name: index参数名称:索引

  1. The SortableBindingList is bound to DataGridView, Virtual mode SortableBindingList 绑定到 DataGridView,虚拟模式
  2. Multiple threads fires event which adds data to SortableBindingList多个线程触发将数据添加到 SortableBindingList 的事件

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

I have tried to lock the SortableBindingList but still getting error, searched a lot but unable to find a solution.我试图锁定 SortableBindingList 但仍然出错,搜索了很多但无法找到解决方案。

Ultimately I suspect it is a false hope to make a truly thread-safe binding list, as there will be cases where multiple operations are performed - regardless of whether that is a "check the Count then iterate rows to Count-1", or "enumerate with foreach " - and there is no easy way to lock over the duration of those, since the calling code is outside of your control.最终我怀疑创建一个真正的线程安全绑定列表是一个错误的希望,因为会有执行多个操作的情况——无论这是“检查计数然后将行迭代到 Count-1”,还是“用foreach枚举“ - 并且没有简单的方法来锁定这些持续时间,因为调用代码不在您的控制范围内。

Even for a half-working version, you'd need to add your syncLock code to every access, via overriding all the available methods - however, I can't see a virtual method for the get on this[index] , which might render that futile - it is only synchronized if all callers agree to use the lock.即使对于半工作版本,您也需要通过覆盖所有可用方法将您的syncLock代码添加到每个访问中 - 但是,我看不到this[index]上的get的虚拟方法,这可能会呈现那是徒劳的——只有在所有调用者都同意使用锁的情况下才会同步。

Ultimately, I suspect that trying to use threading with tight UI coupling is fairly doomed.最终,我怀疑尝试使用具有紧密 UI 耦合的线程是注定要失败的。 IMO, you might have more success separating the two things, and having the UI worry about handling an event and calling .Invoke(...) to update the binding on the UI thread. IMO,您可能会更成功地将这两件事分开,并且让 UI 担心处理事件并调用.Invoke(...)来更新 UI 线程上的绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM