在什么情况下System.Collections.ArrayList.Add会抛出IndexOutOfRangeException?

Jak*_*urc 14 .net collections arraylist

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

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.ArrayList.Add(Object value)
   at ...
Run Code Online (Sandbox Code Playgroud)

根据MSDN Add方法应该只抛出NotSupportedException.

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

Ani*_*Ani 19

IndexOutOfRangeException当"试图与作为阵列的边界之外的索引来访问数组的一个元素."抛出

请注意,ArrayList该类不是线程安全的.在多线程场景中,竞争条件可能会导致ArrayList尝试在超出其范围的索引处读取/写入后备阵列.

示例:一个线程TrimToSize在另一个线程添加到集合的同时减小了后备阵列的大小(可能通过调用).现在,如果支持阵列处于满容量状态,则添加线程将尝试扩展其容量(通过分配新阵列)以容纳新元素.同时TrimToSize呼叫然后反转这种效果.然后,当添加线程尝试写入数组时,它认为可用的索引将不再存在,从而导致抛出异常.

修复:根据您的具体情况使用线程安全的结构.


Tho*_*que 12

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

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


Nem*_*emo 12

归结为List不是线程安全的.我使用多个线程添加项目而没有同步的情况下迭代列表时发生了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
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,updatedFills计数被破坏,后续迭代失败.围绕lock语句包含Add()应该可以防止这种情况.

lock (updatedFills)
{
    updatedFills.Add(fill);
}
Run Code Online (Sandbox Code Playgroud)