2010-09-25 10 views
11

Estamos experimentando errores extraños en el entorno de producción, no podemos depurar ni inyectar código de registro. Estoy tratando de entender esto, pero seguir el rastro de la pila me confunde. Método¿Bajo qué circunstancias System.Collections.ArrayList.Add arroja IndexOutOfRangeException?

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

According to the MSDNAdd sólo debe tirar NotSupportedException.

No tengo idea de lo que está pasando aquí. ¿Vos si?

+0

¿Se puede publicar un stacktrace algo completo? – shahkalpesh

+3

simplemente adivinando: ¿ArrayList se usa en operaciones de subprocesamiento múltiple? –

+0

Puede confirmar el error de concurrencia inspeccionando otros estados de subprocesos en el depurador cuando se produce la excepción. Verifique si alguien más está alterando el contenedor en ese momento. –

Respuesta

7

Todo se reduce a la lista de no ser seguro para subprocesos. He tenido IndexOutOfRangeException occuring cuando se itera sobre una lista después de añadir elementos que utilizan múltiples hilos sin la sincronización de la siguiente manera,

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 
} 

En este caso, se corrompe cuentan updatedFills y falla iteración posterior. Envolver el Add() alrededor de una instrucción de bloqueo debería evitar esto.

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

Se lanza el IndexOutOfRangeException cuando "se intenta acceder a un elemento de una matriz con un índice que está fuera de los límites de la matriz".

Tenga en cuenta que la clase ArrayList no es segura para subprocesos. Es posible que en escenarios de subprocesos múltiples, las condiciones de carrera den como resultado el ArrayList intentando leer/escribir en la matriz de respaldo en índices que están fuera de su rango.

Ejemplo: un hilo reduce el tamaño de la matriz de respaldo (quizás a través de una llamada TrimToSize) al mismo tiempo que se agrega otro hilo a la colección. Ahora, si la matriz de respaldo está a plena capacidad, el hilo de adición intentará expandir su capacidad (asignando una nueva matriz) para acomodar el nuevo elemento. La llamada simultánea TrimToSize invierte este efecto. Luego, cuando el hilo de sumar intenta escribir en la matriz, el índice que pensó que estaba disponible ya no estaría más, lo que provocaría que se lanzara la excepción.

solución: usar construcciones compatibles con el proceso, según corresponda a su situación .

11

Eso es casi seguro un problema de concurrencia ... Es probable que tenga dos hilos que modifiquen la colección al mismo tiempo, y la clase ArrayList no está diseñada para admitir el acceso simultáneo. Se produce una condición de carrera, que a veces lleva a uno de los hilos a intentar escribir en una posición fuera de los límites de la matriz.

tratan de proteger a todos los accesos a la colección usando lock declaraciones, o utilizar un envoltorio sincronizado de la colección (usando el método ArrayList.Synchronized)

Cuestiones relacionadas