2011-03-31 44 views
1

我有一個嵌套循環‘在我的代碼結構’有時候,我得到了以下信息收藏已修改; 。枚舉操作可能不會執行」集合元素不被修改

集合被修改;枚舉操作可能不會執行。

我有一個集合,我通過循環,如下圖所示。CollList<string>

foreach (string[] s1 in obj.Coll 
{ 
    foreach (string s in s1) { } 
} 

對於數組中的每個字符串,我需要ŧ o使用它(讀取爲讀取值,而不是寫入)。 我用它做的所有事情就是獲取目錄(這個值是一個路徑)並將這個字符串拆分成一個數組。

這怎麼解決?

+1

「有時候」是發生了什麼事情的死亡泄露:另一個線程修改了收集。 – Jon 2011-03-31 09:24:14

+0

[C#Collection可能的重複被修改;枚舉操作可能不會執行](http://stackoverflow.com/questions/2024179/c-sharp-collection-was-modified-enumeration-operation-may-not-execute) – nawfal 2013-06-05 17:52:25

回答

0

你可以試試:

foreach (string[] s1 in obj.Coll.ToArray()) 
{ 

這將開始迭代之前採取的副本!

+1

請注意,這隻會工作,如果集合是沒有被另一個線程改變,因爲'ToArray()'不是線程安全的。 – mgronber 2011-03-31 13:11:35

+0

我已經在重負載多線程應用程序中使用了多年,沒有發生任何錯誤或問題,您確定嗎? – 2011-03-31 15:49:08

+0

我編輯了我的答案來證明問題。 – mgronber 2011-03-31 16:51:56

2

obj.Coll在枚舉時發生了變化。如果它沒有被當前線程改變,它可能會被其他線程改變。如果集合被當前線程更改,基本上有兩種方法可以解決問題:您可以創建集合的副本並枚舉副本,或者可以推遲更改,直到枚舉集合。

但是,如果集合被另一個線程更改,則應該以線程安全的方式訪問集合(不僅在這裏,而且在任何地方)。

編輯爲基倫斯通:

我寫了一個短代碼,以證明List<T>.ToArray()不是線程安全的。

var list = new List<int>(); 

Task.Factory.StartNew(() => { 
    for (int i = 0; i < 1000000; ++i) { 
     list.Clear(); 

     // Add values from 1 to 9 
     for (int j = 1; j < 10; ++j) { 
      list.Add(j); 
     } 
    } 

    Console.WriteLine("Thread Exit: list.Add()"); 
}); 

Task.Factory.StartNew(() => { 
    for (int i = 0; i < 100; ++i) { 
     var array = list.ToArray(); 
     if (array.Length > 0) { 
      Console.WriteLine("ToArray(): {0}", string.Join(", ", array)); 
     } 
    } 

    Console.WriteLine("Thread Exit: list.ToArray()"); 
}); 

下面是輸出的片段。我想這證明了我的說法。該片段包含15行,其中9個包含錯誤的數據。

ToArray(): 1, 2, 3, 4 
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0 
ToArray(): 1, 2, 3, 4, 5, 6, 7, 0, 0 
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0, 0 
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0 
ToArray(): 0, 0, 0, 4, 5, 6, 7 
ToArray(): 1, 2, 0, 0, 0, 0, 0, 0, 0 
ToArray(): 1, 2, 3 
ToArray(): 1, 0, 0, 0, 0, 0, 0, 0, 0 
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0 
ToArray(): 1, 2 
ToArray(): 1, 2, 3 
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0 
ToArray(): 1, 2, 3, 4 
ToArray(): 1, 2, 3, 4, 5, 6, 7, 8 

將會有更多的變化,如果我們使用list.Insert(0, j)代替list.Add(j)

相關問題