【问题标题】:Under what circumstance System.Collections.ArrayList.Add throws IndexOutOfRangeException?System.Collections.ArrayList.Add在什么情况下抛出IndexOutOfRangeException?
【发布时间】:2011-04-17 04:31:20
【问题描述】:

我们在生产环境中遇到了奇怪的错误,我们无法调试也无法注入日志记录代码。我正在尝试解决这个问题,但跟踪堆栈跟踪让我感到困惑。

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.ArrayList.Add(Object value)
   at ...

According to the MSDN Add 方法应该只抛出 NotSupportedException

我不知道这里发生了什么。你呢?

【问题讨论】:

  • 你能发布一些完整的堆栈跟踪吗?
  • 只是猜测:ArrayList 用于多线程操作?
  • 当异常发生时,您可以通过在调试器中检查其他线程状态来确认并发错误。检查当时是否有其他人正在更改容器。
  • 最终看起来像是并发问题。
  • 当数组中的元素数为 2 的幂(例如 8、16、32、64 等)时,您可以判断这是并发问题

标签: .net collections arraylist


【解决方案1】:

IndexOutOfRangeException 在“尝试访问具有超出数组边界的索引的数组元素”时抛出。

请注意,ArrayList 类不是线程安全的。在多线程场景中,竞争条件可能会导致ArrayList 尝试在超出其范围的索引处读取/写入支持数组。

示例:一个线程减小了后备数组的大小(可能通过TrimToSize 调用),同时另一个线程正在添加到集合中。现在,如果后备数组已满,添加线程将尝试扩展其容量(通过分配新数组)以容纳新元素。然后同时调用TrimToSize 会反转此效果。然后,当添加线程尝试写入数组时,它认为可用的索引将不再存在,从而引发异常。

修复:根据您的情况使用线程安全构造。

【讨论】:

    【解决方案2】:

    这几乎肯定是并发问题...您可能有两个线程同时修改集合,而ArrayList 类并非旨在支持并发访问。出现竞争条件,有时会导致其中一个线程尝试在数组边界之外的位置写入。

    尝试使用lock 语句保护对集合的所有访问,或使用集合的同步包装器(使用ArrayList.Synchronized 方法)

    【讨论】:

      【解决方案3】:

      归结为 List 不是线程安全的。我在 使用多线程 同步添加项目时迭代列表时发生了 IndexOutOfRangeException。下面的代码可能会破坏项目计数并在随后迭代列表时导致 IndexOutOfRangeException,

      List<TradeFillInfo> updatedFills = new List<TradeFillInfo>();
      Parallel.ForEach (trades, (trade) =>
      {
          TradeFillInfo fill = new TradeFillInfo();
      
          //do something
      
          updatedFills.Add(fill); //NOTE:Adding items without synchronization
      });
      
      foreach (var fill in updatedFills) //IndexOutOfRangeException here sometimes
      {
          //do something
      }
      

      将 Add() 与 lock 语句同步将解决此问题。

      lock (updatedFills)
      {
          updatedFills.Add(fill);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-23
        • 2016-07-16
        • 2011-01-10
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-15
        相关资源
        最近更新 更多