C#中的任务 - 使用随机数的不明确结果

时间:2016-04-03 12:01:31

标签: c# asynchronous parallel-processing task-parallel-library

我正在学习C#中的异步编程,并编写此代码来测试任务并行库(控制台应用程序):

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

}

慢速操作:

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.##"));
    }
}

有谁能帮助我理解为什么SlowOperation类的每个实例产生的总和完全相同?

2 个答案:

答案 0 :(得分:2)

Random根据低分辨率的时间播种。这是一个经典问题,在我看来,这是一个API设计错误。我认为这已经在CoreCLR回购中发生了变化。

new Random().Next() == new Random().Next()几乎总是如此。

另请注意,问题中95%的代码与问题无关。将来,您可以自己简化代码,直到只留下随机调用。这可以让你自己找到这些问题。

答案 1 :(得分:2)

在每项任务中使用不同的种子值进行设置。例如:

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

随机指导员:https://msdn.microsoft.com/pt-br/library/ctssatww(v=vs.110).aspx

  

如果您的应用程序需要不同的随机数序列,请调用   这个构造函数反复使用不同的种子值。一种方法   产生一个独特的种子值是为了使它与时间有关。例如,   从系统时钟导出种子值。但是,系统时钟   可能没有足够的分辨率来提供不同的调用   此构造函数具有不同的种子值。