我们在生产环境中遇到奇怪的错误,我们无法调试或注入日志代码。我试图解决这个问题,但是跟踪堆栈跟踪让我很困惑。
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.ArrayList.Add(Object value)
at ...
According to the MSDN Add
方法只应抛出NotSupportedException
。
我不知道这里发生了什么。你呢?
答案 0 :(得分:19)
当“尝试访问索引超出数组边界的数组元素时,抛出IndexOutOfRangeException
。”
请注意ArrayList
类不是线程安全的。在多线程场景中,竞争条件可能会导致ArrayList
尝试在超出其范围的索引处读取/写入后备阵列。
示例:一个线程在另一个线程添加到集合的同时减小了后备阵列的大小(可能通过TrimToSize
调用)。现在,如果支持阵列处于满容量状态,则添加线程将尝试扩展其容量(通过分配新阵列)以容纳新元素。同时TrimToSize
调用会反转此效果。然后,当添加线程尝试写入数组时,它思想的索引将不再可用,从而导致抛出异常。
修复:根据您的情况使用线程安全结构。
答案 1 :(得分:11)
这几乎肯定是并发问题......您可能有两个线程同时修改集合,ArrayList
类不支持并发访问。出现竞争条件,有时会导致其中一个线程尝试在数组边界之外的位置写入。
尝试使用lock
语句保护对集合的所有访问,或使用集合的同步包装(使用ArrayList.Synchronized
方法)
答案 2 :(得分:10)
归结为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
}
在这种情况下,updatedFills计数被破坏,后续迭代失败。围绕lock语句包含Add()应该可以防止这种情况。
lock (updatedFills)
{
updatedFills.Add(fill);
}