Guid.NewGuid()返回重复?

我们有一个应用程序为我们的某个服务生成模拟数据以进行测试。 每个数据项都有一个唯一的Guid。 但是,当我们在模拟器的一些次要代码更改后运行测试时,它生成的所有对象都具有相同的Guid。

创建了一个数据对象,然后是一个for循环,其中对象的属性被修改,包括一个新的唯一Guid,它通过远程处理发送到服务(可序列化,而不是编组,如果这就是你’思考),循环再做,等等。

如果我们在循环中放入一个小的Thread.Sleep(…),它会生成唯一的id。 我认为这是一个红鲱鱼。 我创建了一个测试应用程序,刚刚创建了一个guid,并没有得到一个副本。

我的理论是IL以一种导致这种行为的方式进行了优化。 但足够我的理论。 你怎么看? 我愿意接受测试的建议和方法。

更新:我的问题似乎有很多混乱,所以让我澄清一下。 我不认为NewGuid()被破坏了。 显然它有效。 没关系! 但是在某处有一个bug会导致NewGuid():1)在我的循环中只调用一次2)在我的循环中每次调用但只分配一次3)其他我没有想过的东西

这个bug可能出现在我的代码中(可能是MOST)或者在某个地方进行优化。

所以重申我的问题,我应该如何调试这个场景?

(谢谢你的精彩讨论,这真的帮助我澄清了我心中的问题)

更新#2:我想发布一个显示问题的例子,但那是我问题的一部分。 我不能在整套应用程序(客户端和服务器)之外复制它。

这是一个相关的片段:

OrderTicket ticket = new OrderTicket(... ); for( int i = 0; i < _numOrders; i++ ) { ticket.CacheId = Guid.NewGuid(); Submit( ticket ); // note that this simply makes a remoting call } 

Submit是否执行异步调用,或者ticket对象是否在任何阶段进入另一个线程。

在代码示例中,您将重用相同的对象。 如果提交在短暂延迟后在后台线程中发送票证(并且不复制),该怎么办? 当您更改CacheId时,实际上正在更新所有待处理的提交。 这也解释了为什么Thread.Sleep修复了这个问题。 试试这个:

 for( int i = 0; i < _numOrders; i++ ) { OrderTicket ticket = new OrderTicket(... ); ticket.CacheId = Guid.NewGuid(); Submit( ticket ); // note that this simply makes a remoting call } 

如果由于某种原因这是不可能的,试试这个,看看它们是否仍然相同:

 ticket.CacheId = new Guid("00000000-0000-0000-0000-" + string.Format("{0:000000000000}", i)); 

成千上万的开发人员在.NET中使用Guids。 如果Guid.NewGuid()有任何倾向于“卡住”一个值,很久以前就会遇到这个问题。

次要代码更改是这里的罪魁祸首。 事实上, Thread.Sleep (不像红色鲱鱼比在阳光下腐烂的鱼)“修复”你的问题表明你的属性是以某种奇怪的方式设置的,直到循环停止阻塞才能生效(或者通过结束或通过Thread.Sleep)。 我甚至愿意打赌,“小改动”是从一个单独的线程重置所有属性。

如果您发布了一些示例代码,那将有所帮助。

这是你的代码中的一个错误。 如果你设法生成多个guid,那么这是最可能的解释。 线索在你的问题中:“当我们在模拟器的一些次要代码更改后运行测试时,它生成的所有对象都具有相同的Guid”

请参阅有关如何创建Guid的文章 。

这个艺术来自于这个答案。

如果您过快地创建GUID并且时钟没有向前移动那么这就是为什么你会得到一些相同的底线。 然而,当你把睡眠放进去时,因为时钟已经移动了。

Submit和OrderTicket中的代码也很有用……

你正在重复使用OrderTicket。 我怀疑你(或远程本身)正在批量调用 – 可能是关于连接数/主机限制 – 并在最终发送它们时获取CacheId的最后一个值。

如果您调试或Thread.Sleep应用程序,您正在更改时间,以便在分配新的CacheId之前完成远程处理调用。

你是否正在拨打远程电话? 我认为同步调用会阻塞 – 但我会检查一下像Wireshark这样的数据包嗅探器。 无论如何,只需改变在每次迭代中创建一个新的OrderTicket就可以了。

编辑:问题不是关于NewGuid被破坏…所以我之前的答案已被删除。

我还不知道如何生成GUID的细节。 但是目前我的组织。 是以一种让兔子感到羞耻的速度繁殖GUID。 所以我可以保证GUID没有被破坏的事实。

  • 如果可能,发布源代码..或克隆repro应用程序。 很多时候,我发现创建克隆应用程序以重现问题的行为向我展示了问题。
  • 另一种方法是评论“那些微小的变化”。 如果这可以解决问题,那么您可以进行三角化以找到有问题的代码行。 小球的变化很难……我的意思是真的很难。

请告诉我们它是怎么回事……这听起来很有趣。

我的直觉告诉我这些方面的事情正在发生……

 class OrderTicket { Guid CacheId {set {_guid = new Guid("00000000-0000-0000-0000-");} } 

每次使用堆栈跟踪调用时,将CacheId的值记录到日志文件中……也许其他人正在设置它。