Dot-Net-4.0
使用並行 for 循環時索引超出範圍異常
我正在嘗試執行以下程式碼,並且在嘗試將數組值分配給列表時不斷收到 Index out of range 異常:-
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]));我在這裡做錯了嗎?我知道該過程是無序/非同步的,但為什麼 “i” 得到的值高於 “array.Length” 的值?
問題是您不能
List.Add()在多個執行緒上同時呼叫。如果您需要執行緒安全的集合,請參閱System.Collections.Concurrent命名空間。如果您在遇到異常時進入調試器,您會看到
i不大於,而是array.Length2 的冪,大大小於array.Length。發生的事情是List從一個空數組開始,比如 4 個元素。每當您將元素添加到數組已滿的列表時,它都會創建一個長度為舊數組兩倍的數組,將舊元素複製到其中,並儲存新數組。現在假設您的列表最多包含 31 個元素(意味著它還有空間容納一個),並且兩個執行緒嘗試添加第 32 個元素。它們都將執行如下程式碼:
if (_size == _items.Length) { EnsureCapacity(_size + 1); } _items[_size++] = item;首先他們都會看到
_size(31) 不是_items.Length(32),所以他們都執行_size++. 第一個執行緒將獲得 31 (第 32 個元素的正確索引)並更改_size為 32。第二個執行緒將獲得 32 並嘗試 index_items[32],這會給您帶來異常,因為它試圖訪問 32 元素數組的第 33 個元素.