Domanda

Sto cercando di eseguire il codice seguente ed io continuo a ricevere un Indice di eccezione gamma quando si cerca di valori di matrice assegnare alla 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]));

sto facendo qualcosa di sbagliato qui? Capisco che il processo è non ordinata / asincrona, ma perché "i" ottengo valori che sono superiori al valore di "Array.length"?

È stato utile?

Soluzione

Il problema è che non si può chiamare List.Add() contemporaneamente su più thread. Se avete bisogno di thread-safe collezioni, vedere lo spazio dei nomi System.Collections.Concurrent.

Se si interrompe nel debugger quando si ottiene un'eccezione, vedrai che i è non maggiore di array.Length, ma è invece una potenza di 2 che è sostanzialmente inferiore array.Length. Succede che il List inizia con una matrice vuota di qualcosa come 4 elementi. Ogni volta che si aggiunge un elemento a una lista i cui gamma è piena, si crea una serie di due volte la lunghezza della vecchia matrice, copia i vecchi elementi ad esso, e memorizza il nuovo array.

Ora diciamo che l'elenco è fino a 31 elementi (il che significa che ha spazio per un altro) e due thread tenta di aggiungere un elemento di 32 °. Essi saranno entrambi eseguire codice in questo modo:

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

In primo luogo essi saranno entrambi vedere che _size (31) non è _items.Length (32), in modo che entrambi eseguono _size++. Il primo thread otterrà 31 (il corretto indice dell'elemento 32 °) e cambio _size a 32. Il secondo filo otterrà 32 e provare a indicizzare _items[32], che vi dà il vostro un'eccezione perché si sta cercando di accedere all'elemento 33 ° di un 32- elemento dell'array.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top