Parallel.ForEach循环行为

时间:2012-03-11 02:59:30

标签: c# random task-parallel-library parallel.foreach

这是一些示例测试应用程序,我试图学习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'中的随机值对于来自月份列表的一对企业显示相同,而一个或可能是2将具有不同的随机值。为什么这样做呢?并行循环不应为每次迭代创建新的随机值。如果我使用parallelOptions并将Parallelism的MaxDegree设置为1,那么我在变量'i'中看到不同的值

请指导我理解并行循环。

1 个答案:

答案 0 :(得分:2)

这是因为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));
}

**请注意,此示例不保证唯一性,但仅作为生成种子值的方式显示**