Question

Je suis en train d'exécuter le code suivant et je continue à obtenir un indice hors d'exception plage lorsque vous essayez d'attribuer des valeurs de tableau à la liste: -

        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]));

Est-ce que je fais quelque chose de mal ici? Je comprends que le processus est non ordonnée / asynchrone, mais pourquoi obtenir des valeurs « i » qui sont supérieurs à la valeur de « array.length »?

Était-ce utile?

La solution

Le problème est que vous ne pouvez pas appeler List.Add() simultanément sur plusieurs threads. Si vous avez besoin de collections thread-safe, voir l'espace de noms System.Collections.Concurrent.

Si vous cassez dans le débogueur lorsque vous obtenez une exception, vous verrez que i est pas supérieur à array.Length, mais est au contraire une puissance de 2 qui est sensiblement inférieure à array.Length. Ce qui se passe est que le List commence avec un tableau vide de quelque chose comme 4 éléments. Chaque fois que vous ajoutez un élément à une liste dont tableau est complet, il crée un tableau de la longueur de l'ancien tableau deux fois, copie les anciens éléments à elle, et stocke le nouveau tableau.

Maintenant, disons que votre liste est jusqu'à 31 éléments (ce qui signifie qu'il ya un espace pour un plus) et deux fils essayer d'ajouter un élément 32e. Ils seront tous deux exécuter du code comme ceci:

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

D'abord, ils seront tous les deux voir que _size (31) ne sont pas _items.Length (32), donc ils ont tous deux exécuter _size++. Le premier fil obtiendra 31 (l'indice correct de l'élément 32e) et changer _size à 32. Le deuxième fil va se 32 et essayer d'indexer _items[32], ce qui vous donne votre exception parce qu'il tente d'accéder à l'élément 33 d'un 32- groupement d'éléments.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top