2010-04-07 82 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