为什么C#Parallel.ForEach抛出IndexOutOfBounds和foreach不?

时间:2012-10-06 20:27:27

标签: c# parallel-processing

我制作了这个小程序来测试并行化。

当我多次点击button1时,它会以IndexOutOfBounds异常结束。我想这是因为我的内存不足。为什么我使用并行化而不是常规foreach(按钮2单击)?

private void button1_Click(object sender, EventArgs e)
{
    var s = Stopwatch.StartNew();

    int[] nums = new int[10000];
    List<int> randoms = new List<int>();

    Parallel.ForEach(nums, i =>
    {
        randoms.Add(new Random().Next());
    });

    s.Stop();
    label1.Text = "Added " + randoms.Count() + " randoms in "
                  + s.Elapsed.Milliseconds.ToString() + " milliseconds";
}

private void button2_Click(object sender, EventArgs e)
{
    var s = Stopwatch.StartNew();

    int[] nums = new int[10000];
    List<int> randoms = new List<int>();
    foreach (var i in nums)
    {
        randoms.Add(new Random().Next());
    }

    s.Stop();
    label2.Text = "Added " + randoms.Count() + " randoms in "
                  + s.Elapsed.Milliseconds.ToString() + " milliseconds";
}

2 个答案:

答案 0 :(得分:2)

Parallel.ForEach代码中,您同时修改了一个非线程安全的List<int>

当您在另一个线程中调整内部数组的大小时,尝试添加到List的末尾时会发生异常。

相反,您应该使用ConcurrentBagConcurrentQueue

等并发集合

答案 1 :(得分:2)

您正在并行修改randoms。这是一个错误,因为列表对于并发添加是不安全的。

此外,IndexOutOfBounds与内存不足无关。您可以通过仔细查看异常来找到所有这些:消息告诉您它不是OOM。堆栈跟踪告诉您错误发生在哪一行(它位于Add - 行,对吧?)。