0

並列化をテストするためにこの小さなプログラムを作成しました。

button1を数回押すと、IndexOutOfBounds例外が発生します。これは、メモリが不足しているためだと思います。通常のforeach(button2クリック)ではなく、並列化でこれを取得するのはなぜですか?

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";
}
4

2 に答える 2

2

あなたのParallel.ForEachコードでは、スレッドセーフではないを同時に変更しList<int>ています。

List例外は、内部配列が別のスレッドでサイズ変更されている間に、最後に追加しようとしたときに発生します。

ConcurrentBag代わりに、またはのような並行コレクションを使用する必要がありますConcurrentQueue

于 2012-10-06T20:30:07.737 に答える
2

randoms並行して変更しています。リストは同時追加には安全ではないため、これはバグです。

また、IndexOutOfBoundsはメモリ不足とは何の関係もありません。例外を注意深く見ることで、これらすべてを見つけることができます。メッセージは、それがOOMではないことを示しています。そして、スタックトレースは、エラーが発生した行を示します(-行にありましたAddよね?)。

于 2012-10-06T20:30:53.860 に答える