Bartosz
Bartosz

Reputation: 4592

Tasks in C# - unclear outcome using Random

I'm learning about async programming in C#, and written this code to test Task Parallel Library (Console application):

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();

    var opr1 = new SlowOperation();
    var opr2 = new SlowOperation();

    //TASK
    Console.WriteLine("Started processing using TASK. Start: {0}", sw.Elapsed);
    sw.Start();

    Task.Factory.StartNew(() => opr1.PerformSlowOperation(1));
    Task.Factory.StartNew(() => opr2.PerformSlowOperation(2));

    Console.WriteLine("Stopped processing using TASK. Stop: {0}", sw.Elapsed);
    sw.Stop();

}

where slow operation is:

public class SlowOperation
{
    public void PerformSlowOperation(int id)
    {
        var rand = new Random();
        double sum = 0;

        for (int i = 0; i < 100000000; i++)
        {
            var number = Convert.ToDouble(rand.Next(100)) / 100;
            sum += number;
        }
        Console.WriteLine("Finished processing operation no. {0}. Final sum calculated is: {1}", id, sum.ToString("0.##"));
    }
}

Could anyone please help me to understand why sum produced by each instance of SlowOperation class is exactly the same?

Upvotes: 4

Views: 364

Answers (2)

Adriano Godoy
Adriano Godoy

Reputation: 1568

Set with a different seed value in each task. For example:

var rand = new Random(new System.DateTime().Millisecond + id);

Random construtor: https://msdn.microsoft.com/pt-br/library/ctssatww(v=vs.110).aspx

If your application requires different random number sequences, invoke this constructor repeatedly with different seed values.One way to produce a unique seed value is to make it time-dependent.For example, derive the seed value from the system clock.However, the system clock might not have sufficient resolution to provide different invocations of this constructor with a different seed value.

Upvotes: 2

usr
usr

Reputation: 171188

Random is seeded based on time at a low resolution. This is a classic issue and, in my mind, an API design error. I think this is already changed in the CoreCLR repo.

new Random().Next() == new Random().Next() is almost always true.

Also note, that 95% of the code in the question has nothing to do with the problem. In the future you can simplify the code yourself until only the random call is left. That allows you to find such problems yourself.

Upvotes: 2

Related Questions