.net 4.0 使用并行for循环时索引超出范围异常
我正在尝试执行以下代码,在尝试将数组值分配给列表时,我不断获得索引超出范围的异常:-.net 4.0 使用并行for循环时索引超出范围异常,.net-4.0,parallel-processing,task-parallel-library,.net 4.0,Parallel Processing,Task Parallel Library,我正在尝试执行以下代码,在尝试将数组值分配给列表时,我不断获得索引超出范围的异常:- int[] array = new int[1000000]; for (int i = 0; i < array.Length; i++) { array[i] = i; } List<int> list = new List<int>(); Parallel
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]));
int[]数组=新的int[1000000];
for(int i=0;ilist.Add(array[i]));
我做错什么了吗?我知道该进程是无序/异步的,但是为什么“I”得到的值高于“array.Length”的值呢?问题是,您不能在多个线程上同时调用
List.Add()
。如果需要线程安全集合,请参阅System.collections.Concurrent
命名空间
如果在出现异常时闯入调试器,您将看到i
不大于array.Length
,而是大大小于array.Length
的2的幂。发生的情况是,列表
以一个类似4个元素的空数组开始。每当向数组已满的列表中添加元素时,它都会创建一个长度为旧数组两倍的数组,将旧元素复制到该数组中,并存储新数组
现在让我们假设您的列表最多有31个元素(这意味着它还有一个元素的空间),两个线程尝试添加第32个元素。它们都将执行如下代码:
if (_size == _items.Length)
{
EnsureCapacity(_size + 1);
}
_items[_size++] = item;
首先,它们都会看到
\u size
(31)不是\u items.Length
(32),因此它们都执行\u size++
。第一个线程将得到31(第32个元素的正确索引),并将\u size
更改为32。第二个线程将得到32,并尝试索引\u items[32]
,这会给您一个异常,因为它试图访问32元素数组的第33个元素。回答得很好。我希望我能投两次赞成票。我将在下一篇博文中引用这一点;我希望你不介意。