El problema es que no puede llamar al List.Add()
al mismo tiempo en varios subprocesos. Si necesita colecciones seguras para hilos, consulte el espacio de nombres System.Collections.Concurrent
.
Si se rompe en el depurador cuando recibe una excepción, se verá que es i
no mayor que array.Length
, sino que es una potencia de 2 que es sustancialmente menor que array.Length
. Lo que sucede es que el List
comienza con una matriz vacía de algo así como 4 elementos. Cada vez que agrega un elemento a una lista cuya matriz está llena, crea una matriz de dos veces la longitud de la matriz anterior, copia los elementos antiguos en ella y almacena la nueva matriz.
Ahora digamos que su lista es de hasta 31 elementos (lo que significa que tiene espacio para uno más) y dos hilos intentan agregar un 32º elemento. Serán tanto ejecutar código como este:
if (_size == _items.Length)
{
EnsureCapacity(_size + 1);
}
_items[_size++] = item;
En primer lugar se va a ver que tanto _size
(31) no es _items.Length
(32), por lo que ambos ejecutar _size++
. El primer subproceso obtendrá 31 (el índice correcto del 32º elemento) y cambiará a _size
por 32. El segundo subproceso tendrá 32 e intentará indexar _items[32]
, lo que le ofrece su excepción porque está intentando acceder al 33º elemento de un 32- elemento de matriz.
Excelente respuesta. Ojalá pudiera votarlo dos veces. Voy a hacer referencia a esto en mi próxima publicación de blog; Espero que no te moleste. –
+1 gran respuesta genial, gracias gabe! – andy