在开始之前,我想指出,我非常确定这确实发生了。我所有的日志都表明确实如此。
我想知道我是否错了,这是不可能的,是否只是难以置信地不可能(我怀疑),或者如果不是那么不可能,我做的事情从根本上是错误的。强>
我在同一台服务器上有 4 个相同代码的实例作为 Windows 服务运行。此服务器具有多核 (4) 处理器。
这里是代码的总结:
public class MyProcess
{
private System.Timers.Timer timer;
// execution starts here
public void EntryPoint()
{
timer = new System.Timers.Timer(15000); // 15 seconds
timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
timer.AutoReset = false;
Timer_Elapsed(this, null);
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
string uid = GetUID();
// this bit of code sends a message to an external process.
// It uses the uid as an identifier - these shouldn't clash!
CommunicationClass.SendMessage(uid);
timer.Start();
}
// returns an 18 digit number as a string
private string GetUID()
{
string rndString = "";
Random rnd = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < 18; i++)
{
rndString += rnd.Next(0, 10);
}
return rndString;
}
接收这些消息的外部进程感到困惑 - 我认为是因为相同的 uid 来自两个不同的进程。基于此,看来 GetUID()
方法为两个单独的进程返回相同的“随机”18 位字符串。
我已经使用 DateTime.Now.Ticks 为 Random 类播种,我认为它可以在线程之间提供保护 - 一个滴答为 100 纳秒,两个线程肯定无法获得相同的种子值。
我显然没有考虑到的是,我们不是在谈论线程,我们是在谈论多核处理器上的进程。这意味着这段代码可以字面上同时运行两次。我认为这就是导致冲突的原因。
以大约 15 秒的间隔运行相同代码的两个进程设法在 100 纳秒内命中相同的代码。这可能吗?我走在正确的轨道上吗?
如果您有任何想法或建议,我将不胜感激。
澄清一下,我不能真正使用 GUID - 与我通信的外部进程需要一个 18 位数字。它很旧,很遗憾我无法更改它。
最佳答案
除非有某些原因你不能,否则你应该考虑使用 GUID以此目的。您将以这种方式消除碰撞。
根据评论:您可以使用 GUID 和 64 位 FNV hash并使用 XOR-folding使您的结果在您拥有的 59 位以内。不像 GUID 那样防碰撞,但比您拥有的更好。
关于c# - 随机数在不同进程中与相同的 .Net 代码发生冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1134738/