2010-04-07 84 views
9

我有一個特定的方法是偶爾用一個ArgumentException崩潰:LIST <>的AddRange拋出ArgumentException的

Destination array was not long enough. Check destIndex and length, and the array's lower bounds.: 
at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable) 
at System.Collections.Generic.List`1.CopyTo(T[] array, Int32 arrayIndex) 
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection) 
at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection) 

導致此崩潰的代碼看起來是這樣的:

List<MyType> objects = new List<MyType>(100); 
objects = FindObjects(someParam); 
objects.AddRange(FindObjects(someOtherParam); 

根據MSDN,列表<> .AddRange()應根據需要自動調整其大小:

如果新計數(當前計數加上集合的大小)將大於容量,則通過自動重新分配內部數組以適應新元素來增加列表<(Of> <(T>)>)的容量,並且在添加新元素之前將現有元素複製到新數組中。

有人能想到AddRange可以拋出這種異常的情況嗎?


編輯:

響應於關於FindObjects問題()方法。它基本上看起來像這樣:

List<MyObject> retObjs = new List<MyObject>(); 

foreach(MyObject obj in objectList) 
{ 
    if(someCondition) 
     retObj.Add(obj); 
} 
+1

FindObjects返回什麼?另外,爲什麼初始化'objects'然後及時在下一行重新分配它? – 2010-04-07 14:31:38

+0

當您添加一個項目時,它會檢查大小是否足夠大,如果不是,則調整它使用的內部數組大小。然而,當使用多線程時,可以檢查,獲取false並調整數組大小,下一個線程讀取的是足夠的空間並且不調整大小,然後它們都會到達實際的'this._items [this._size ++] = item ;'代碼在同一時間...導致後者線程爆炸。當Jon說'List '在下面的答案中不是線程安全的,這是'List '不能處理的事情之一。 – 2010-04-07 14:39:52

+0

我沒有寫代碼,我只是在調試這個問題。有很多奇怪的東西,維護人員在翻找時發現:) – Tim 2010-04-07 14:41:07

回答

20

您是否嘗試從多個線程更新相同的列表?這可能會導致問題... List<T>是不安全的多個作家。

+0

FindObjects()方法本身實例化一個新的List <>對象,填充它並返回它。它們都是單線程的,所以我不認爲有多個線程可以在列表中工作。 – Tim 2010-04-07 14:39:56

+0

@Tim:然後我看不出爲什麼會發生。看看你是否可以想出一個簡短但完整的程序來展示問題。如果我們能夠重現它,我們應該能夠修復它。 – 2010-04-07 14:46:36

+0

這或多或少是我希望聽到的。我一直無法重現這個問題,在我看來,它似乎不應該發生。我只是想確保我沒有錯過任何東西,然後直接拒絕它作爲一個問題。 – Tim 2010-04-07 14:52:50

0

老實說,我不確定,但爲什麼不只是刪除您的列表初始化的大小聲明?

List`<MyType>` list = new List`<MyType>` 
+3

因爲該初始化被及時丟棄。它甚至不需要*以這種方式進行初始化。 – 2010-04-07 14:44:04