2

これは、Parallel.Foreach ループ機能を学習しようとしているサンプル テスト アプリです。

static void Main(string[] args)
{
   List<string> Months = new List<string>()
   {
      "Jan", "Feb", "Mar", "Apr", "May", "June" 
   };
   Parallel.ForEach(Months, (x) => ProcessRandom(x));
   Console.ReadLine();
}

public static void ProcessRandom(string s)
{
     Random r = new Random();
     int i = r.Next(1, 100);
     Thread.Sleep(1000);
     Console.WriteLine(string.Format("Month Name {0} and Random ID assigned {1}", s, i));
}

foreach の並列処理についての私の理解では、リストのパラメーターを使用して ProcessRandom メソッドを並列に実行するということです。そのメソッド内のすべての変数は分離され、互いに独立して実行されます。しかし、実行すると、整数 'i' に格納されているランダム値が月リストのいくつかのエントリで同じであることを示し、1 つまたは 2 つのランダム値が異なることがわかります。なぜこれはそのように振る舞うのですか?反復ごとに新しいランダム値を作成する並列ループはすべきではありません。parallelOptions を使用し、Parallelism の MaxDegree を 1 に設定すると、変数 'i' に異なる値が表示されます

並列ループを理解するために私を導いてください。

4

1 に答える 1

3

これは、Random が実際にはランダムではなく疑似ランダムであるためです ( http://msdn.microsoft.com/en-us/library/system.random.aspx )。この正確な問題は、MSDN 記事のコメントに記載されています。複数のインスタンスが同時に作成され、両方のインスタンスで .Next() が呼び出されると、同じ結果になる可能性があります (システム クロックの分解能が限られているため)。これに対処するには、反復ごとに一意のシードを作成する必要があります。そのためには、次のようなことができます (ただし、この猫の皮を剥ぐ方法はたくさんあります)。

static void Main(string[] args)
{
    List<string> Months = new List<string>() { "Jan", "Feb", "Mar", "Apr", "May", "June" };
    Parallel.ForEach(Months, (x) => ProcessRandom(x));
    Console.ReadLine();
}

public static void ProcessRandom(string s)
{            
    Random r = new Random(s.GetHashCode());
    int i = r.Next(1, 100);
    Thread.Sleep(1000);
    Console.WriteLine(string.Format("Month Name {0} and Random ID assigned {1}", s, i));
}

** この例は一意性を保証するものではなく、シード値を生成する方法として示されているだけであることに注意してください **

于 2012-03-11T03:10:01.047 に答える