在我朋友的代码中,他有List
:
List<int> listOfIds = new List<int>();
然后我用AddRange()
向它添加了一个int集合:
listOfIds.AddRange(this._employeeList
.Where(r => r.EmployeeID != null)
.Select(r => r.EmployeeID != null ? r.EmployeeID.Value : 0));
然后,在日志中,它说:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
at the method which called the codes above.....
我不确定为什么会这样。我很确定这个错误发生在上面的代码中,但我似乎无法理解为什么IndexOutofRangeException
会出现。
你能帮我指出导致这种情况的原因吗?
更新
我错了。我很抱歉。该方法不使用多线程。但是,调用此方法的另一种方法是使用Parallel.Foreach,这意味着多线程。有可能当_employeeList被用作AddRange()的源时,另一个线程也在修改它。因此,addrange()不是线程安全的答案是合理的。非常感谢你们。
答案 0 :(得分:2)
很难说出更具体的想法,但这可能有用。
AddRange
不是线程安全的。尝试使用lock primitives
添加许多项目。声明:
private static object mutex = new object();
用法
lock(mutex)
{
listOfIds.AddRange( /* code goes here */ )
}
在AddRange
找到
public void AddRange(IEnumerable<T> collection)
{
this.InsertRange(this._size, collection);
}
InsertRange
的内容,您可以在堆栈跟踪中看到:
...
ICollection<T> collection1 = collection as ICollection<T>;
if (collection1 != null)
{
...
}
else
{
foreach (T obj in collection)
this.Insert(index++, obj);
}
换句话说 - 它迭代序列并尝试使用递增索引逐项添加。这应该不会出错,是吗?由845
反编译的List.cs
行dotPeek
。所以我不相信堆栈跟踪,除了我会看到整个跟踪。