kmaal Ah.
kmaal Ah.

Reputation: 23

Parallel.ForEach loop behavior

This is some sample test app i trying to learn Parallel.Foreach Loop functionality

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));
}

My understanding about foreach in parallel is that it will run the ProcessRandom method with a parameter from the list in parallel. All the variables inside that method will be seperate and they will run independant of one another. But when i run i see that the random value stored in integer 'i' shows same for couple of enteries from the months list and one or may be 2 will have different random values. Why is this behaving like that. Shouldn't the parallel loop creating new random value for each iteration. If i use parallelOptions and set MaxDegree of Parallelism to 1 then i see different values in variable 'i'

Please guide me in understanding of parallel loops.

Upvotes: 2

Views: 1251

Answers (1)

Gary.S
Gary.S

Reputation: 7121

This happens because Random isn't really random but pseudo-random (http://msdn.microsoft.com/en-us/library/system.random.aspx). This exact issue is mentioned in the remarks of the MSDN article. When multiple instances are created at the same time and .Next() is call on both instances, it is possible they will end up with the same result (due to finite system clock resolution). To deal with this we should create a unique seed for each iteration. To that end you could do something like this (but there are many ways to skin this cat):

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));
}

** Note that this example does not guarantee uniqueness but is just shown as a way to generate a seeded value **

Upvotes: 3

Related Questions