2010-10-24 98 views
6

我想執行以下代碼,我不斷收到指數超出範圍的異常試圖數組分配值列表時: -索引超出範圍例外的for循環

 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」的值高呢?

回答

15

問題是,您不能在多個線程上同時調用List.Add()。如果您需要線程安全的集合,請參閱System.Collections.Concurrent命名空間。

如果中斷調試程序時,你會得到一個異常,你會看到iarray.Length更大,但不是2的冪實質上小於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並嘗試索引_items[32],這會給您帶來例外,因爲它試圖訪問32位元素的第33個元素,元素數組。

+2

優秀的答案。我希望我可以投它兩次。我將在我的下一篇博客文章中引用它;我希望你不介意。 – 2010-12-17 11:54:10

+0

+1很棒的答案,謝謝gabe! – andy 2012-11-08 23:32:52

相關問題