11

重複の可能性:
並列処理中のC#値の保存

今日、コンソールアプリケーションでいくつかのパフォーマンステストを実行していましたが、本当に予期しない何かに遭遇しました。私のコード:

int iterations = 1000000;

var mainList = new List<string>();

for (int i = 0; i < iterations; i++)
{
    mainList.Add(i.ToString());
}

var listA = new List<string>();

Parallel.ForEach(mainList, (listItem) =>
                           {
                               if (Int32.Parse(listItem)%2 == 0)
                               {
                                   listA.Add(listItem);
                               }
                           });

Console.WriteLine("Parallel Count: {0}", listA.Count);

var listB = new List<string>();
foreach (var listItem in mainList)
{
    if (Int32.Parse(listItem) % 2 == 0)
    {
        listB.Add(listItem);
    }
}

Console.WriteLine("Sequential Count: {0}", listB.Count);

その結果、次の出力が得られました。

並列カウント:495939

シーケンシャルカウント:500000

何度か実行しましたが、並列ループが適切な回数実行されていないようです。誰かがこの「不正行為」を説明できますか?並列ループは信頼できますか?

PS整数に対するToString()呼び出しのような提供されたコードの例では、それらを解析して戻すよりも多くのナンセンスが起こっていることを私は知っていますが、それはテスト中に思いついた単なるランダムなコードでした。前もって感謝します。

4

1 に答える 1

15

あなたの問題はではありませんParallel.ForEach。あなたの問題はList<int>-クラスはスレッドセーフではありません。私の推測では、リストオブジェクトでスレッドセーフの問題が発生していると思います。代わりに使用してみてくださいConcurrentBag<int>。そうすれば、問題はおそらく消えます。

のスレッドセーフList<T>に関するMicrosoftから:

読み取りと書き込みのために複数のスレッドがコレクションにアクセスできるようにするには、独自の同期を実装する必要があります。

于 2012-12-29T18:31:20.437 に答える