Frage

Ich versuche, den folgenden Code auszuführen, und ich halte einen Index außerhalb des zulässigen Bereichs Ausnahme erhalten, wenn auf der Liste zu assign Array-Werte versuchen: -

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

Bin ich denn hier etwas nicht in Ordnung? Ich verstehe, dass der Prozess ungeordneten ist / asynchron, aber warum ist „i“ erhalten Werte, die höher sind als der Wert von „Array.length“?

War es hilfreich?

Lösung

Das Problem ist, dass Sie nicht List.Add() gleichzeitig auf mehreren Threads aufrufen können. Wenn Sie Sammlungen-Thread-sicher benötigen, finden Sie in der System.Collections.Concurrent Namespace.

Wenn Sie in den Debugger unterbrechen, wenn Sie eine Ausnahme zu bekommen, werden Sie sehen, dass i ist nicht größer als array.Length, sondern ist eine Potenz von 2, die wesentlich geringer ist als array.Length. Was passiert, ist, dass der List beginnt mit einer leeren Reihe von so etwas wie 4 Elementen. Jedes Mal, wenn Sie ein Element in eine Liste, dessen Array voll ist hinzuzufügen, erstellt es eine Reihe von doppelter Länge des alten Array, kopiert die alten Elemente, um es, und speichert das neue Array.

Nun lasst uns sagen, dass Ihre Liste ist auf 31 Elemente auf (dh es ist Platz für ein weiteres hat) und zwei Threads versuchen, einen 32. Element hinzuzufügen. Sie werden beide Ausführen von Code wie folgt aus:

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

Zuerst werden sie sehen beide, dass _size (31) ist nicht _items.Length (32), so dass beide sie _size++ ausführen. Der erste Thread bekommt 31 (den korrekten Index des 32. Element) und Änderung _size bis 32. Der zweite Thread 32 erhalten wird, und versuchen Sie zu indizieren _items[32], mit dem Sie Ihre Ausnahme gibt, weil es das 33. Element eines zuzugreifen versucht, 32- Elementanordnung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top