关于c#:为什么在彼此之后创建的两个任务会生成相同的随机值?

Why do two tasks created after each other generate the same random value?

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
7
8
9
Task.Factory.StartNew(() =>
    {
    new Class1();
    })

Task.Factory.StartNew(() =>
    {
    new Class2();
    })

在Class1和Class2的构造函数中,我有:

1
2
var timeout = new Random().Next(0, 5000);
Debug.Print(timeout.ToString());

两个类中的随机值"timeout"总是相同的。我不明白为什么……

如果我在创建任务之间添加了一个停顿,那么它就不一样了。

编辑:

我不明白这和"返回相同字符串的随机字符串生成器"有什么关系。

他正在创建方法中的随机实例。我称之为完全不同的任务,所以他们应该彼此独立。


BLCK1

虽然根本原因是相同的,但这并不是直接相关的。一个更好的复制方法是这个问题:为什么我要一直在代码中得到两个相同的随机值?

它包含了对EDOCX1对文档所做操作的解释:

墨水

换句话说:如果您快速连续地创建EDOCX1-0对象,它们将产生相同的随机数序列。

BLCK1—2

不管这些对象是在不同的线程(或EDOCX1-3-s)中创建的,都是无关紧要的,它们只依赖于创建时的系统时间,而不依赖于其他任何东西。就像你说的,它们实际上是相互独立的。但它们都依赖于相同的种子值,即创建时的系统时间。

解决这个问题的正确方法通常是只有一个EDOCX1类的实例。实际上,这样的代码:EDOCX1-5是代码味道,因为它错误地使用了EDOCX1类:您不应该为每个调用生成新的实例;相反,您应该重用同一个实例来生成一个随机数序列。

不幸的是,您不能简单地在不同的竞争对手任务中使用相同的EDOCX1或实例,因为相关的方法不是线程安全的,也就是说,从多个线程同时调用它可能导致竞争条件。有几种方法可以解决这个问题,但最简单的方法是使用显式锁:

ZZU1

需要注意的是,必须锁定对EDOCX1的每个访问,否则这是没有意义的。

现在,您可以创建和运行任务,并获得适当的随机性:

ZZU1

请注意,当省略EDOCX1到9块时,您可能会得到正确的结果。这是使用并发性和随机性的危险:很难验证您的结果是否是正确的,或者是否在过程中被损坏。所以要谨慎行事。


无参数EDOCX1类构造函数使用与时间相关的方法来确定随机数生成算法的初始种子。

ZZU1

这就是为什么当您同时创建实例时,它们将生成相同的结果。