Pergunta

Estou tentando executar o código a seguir e continuo obtendo um índice fora da exceção do alcance ao tentar atribuir valores de matriz à lista:-

        int[] array = new int[1000000];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = i;
        }

        List<int> list = new List<int>();
        Parallel.For(0, array.Length, i => list.Add(array[i]));

Estou fazendo algo errado aqui? Entendo que o processo não é ordenado/assíncrono, mas por que "eu" obtém valores mais altos que o valor de "Array.length"?

Foi útil?

Solução

O problema é que você não pode ligar List.Add() simultaneamente em vários threads. Se você precisar de coleções seguras de tópicos, consulte o System.Collections.Concurrent espaço para nome.

Se você invadir o depurador quando tiver uma exceção, verá que verá que i é não Maior que array.Length, mas é um poder de 2 que é substancialmente menor que array.Length. O que acontece é que o List Começa com uma variedade vazia de algo como 4 elementos. Sempre que você adiciona um elemento a uma lista cuja matriz está cheia, ela cria uma variedade de duas vezes o comprimento da matriz antiga, copia os elementos antigos e armazena a nova matriz.

Agora, digamos que sua lista está até 31 elementos (o que significa que tem espaço para mais um) e dois threads tentam adicionar um 32º elemento. Ambos executarão o código como este:

if (_size == _items.Length)
{
    EnsureCapacity(_size + 1);
}
_items[_size++] = item;

Primeiro, ambos verão isso _size (31) não é _items.Length (32), então os dois executam _size++. O primeiro tópico receberá 31 (o índice correto do 32º elemento) e mudará _size para 32. O segundo tópico receberá 32 e tentará indexar _items[32], o que dá sua exceção porque está tentando acessar o 33º elemento de uma matriz de 32 elementos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top