Under what circumstance System.Collections.ArrayList.Add throws IndexOutOfRangeException?
The IndexOutOfRangeException
is thrown when "an attempt is made to access an element of an array with an index that is outside the bounds of the array."
Note that the ArrayList
class is not thread-safe. It is possible that in multi-threaded scenarios, race-conditions will result in the ArrayList
attempting to read/write to the backing array at indices that are outside its range.
Example: One thread reduces the size of the backing array (perhaps through a TrimToSize
call) at the same time that another thread is adding to the collection. Now, if the backing array is at full capacity, the adding thread will attempt to expand its capacity (by allocating a new array) to accomodate the new element. The simultaneous TrimToSize
call then reverses this effect. Then, by the time the adding thread attempts to write to the array, the index that it thought was available would no longer be, causing the exception to be thrown.
Fix: Use thread-safe constructs, as appropriate to your situation.
It boils down to List not being thread safe. I have had IndexOutOfRangeException occuring when iterating over a list after adding items using multiple threads without synchronization. The code below could corrupt the items count and result in IndexOutOfRangeException while iterating the list subsequently,
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
}
Synchronizing the Add() with a lock statement will fix the issue.
lock (updatedFills)
{
updatedFills.Add(fill);
}
That's almost certainly a concurrency issue... You probably have two threads that modify the collection at the same time, and the ArrayList
class is not designed to support concurrent access. A race condition occurs, which sometimes leads one of the threads to attempt to write at a position outside the bounds of the array.
Try to protect all accesses to the collection using lock
statements, or use a synchronized wrapper of the collection (using the ArrayList.Synchronized
method)