C# Guid.NewGuid() 返回的重复项?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/300786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 22:17:03  来源:igfitidea点击:

Duplicate returned by Guid.NewGuid()?

c#guid

提问by dviljoen

We have an application that generates simulated data for one of our services for testing purposes. Each data item has a unique Guid. However, when we ran a test after some minor code changes to the simulator all of the objects generated by it had the same Guid.

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

There was a single data object created, then a for loop where the properties of the object were modified, including a new unique Guid, and it was sent to the service via remoting (serializable, not marshal-by-ref, if that's what you're thinking), loop and do it again, etc.

创建了一个数据对象,然后是一个 for 循环,其中修改了对象的属性,包括一个新的唯一 Guid,并通过远程处理将其发送到服务(可序列化,而不是按引用编组,如果这是您'正在思考),循环并再次执行,等等。

If we put a small Thread.Sleep( ...) inside of the loop, it generated unique id's. I think that is a red-herring though. I created a test app that just created one guid after another and didn't get a single duplicate.

如果我们在循环内放一个小的 Thread.Sleep( ...) ,它会生成唯一的 id。我认为这是一个红鲱鱼虽然。我创建了一个测试应用程序,它只是一个接一个地创建了 guid,但没有得到一个重复项。

My theory is that the IL was optimized in a way that caused this behavior. But enough about my theories. What do YOU think? I'm open to suggestions and ways to test it.

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

UPDATE: There seems to be a lot of confusion about my question, so let me clarify. I DON'T think that NewGuid() is broken. Clearly it works. Its FINE! There is a bug somewhere though, that causes NewGuid() to either: 1) be called only once in my loop 2) be called everytime in my loop but assigned only once 3) something else I haven't thought of

更新:我的问题似乎有很多困惑,所以让我澄清一下。我不认为 N​​ewGuid() 坏了。显然它有效。没关系!虽然某处有一个错误,导致 NewGuid() 要么:1) 在我的循环中只被调用一次 2) 在我的循环中每次被调用但只分配一次 3) 我没有想到的其他事情

This bug can be in my code (MOST likely) or in optimization somewhere.

这个错误可能在我的代码中(很可能)或在某个地方的优化中。

So to reiterate my question, how should I debug this scenario?

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

(and thank you for the great discussion, this is really helping me clarify the problem in my mind)

(并感谢您的精彩讨论,这确实帮助我澄清了我心中的问题)

UPDATE # 2: I'd love to post an example that shows the problem, but that's part of my problem. I can't duplicate it outside of the whole suite of applications (client and servers).

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

Here's a relevant snippet though:

不过,这是一个相关的片段:

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
}

采纳答案by Robert Wagner

Does Submit do an async call, or does the ticket object go into another thread at any stage.

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

In the code example you are reusing the same object. What if Submit sends the ticket in a background thread after a short delay (and does not take a copy). When you change the CacheId you are actually updating all the pending submits. This also explains why a Thread.Sleep fixes the problem. Try this:

在代码示例中,您正在重用相同的对象。如果 Submit 在短暂延迟后在后台线程中发送票证(并且不复制)怎么办。当您更改 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
}

If for some reason this is not possible, try this and see if they are still the same:

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

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

回答by Mitch Wheat

It's a bug in your code. If you've managed to generate multiple guid's it is the most likely explanation. The clue is here in your question: "when we ran a test after some minor code changes to the simulatorall of the objects generated by it had the same Guid"

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

回答by David Basarab

See this articleabout how a Guid is created.

请参阅这篇关于如何创建 Guid 的文章

This artcile came from Thisanswer.

这篇文章来自这个答案。

Bottom line if you are creating the GUIDs too quickly and the clock hasn't moved forward that is why you are getting some as the same. However when you put a sleep in it works because the clock has moved.

最重要的是,如果您创建 GUID 的速度太快并且时钟没有向前移动,这就是为什么您会得到相同的结果。但是,当您进入睡眠状态时,它会起作用,因为时钟已经移动了。

回答by Mark Brackett

The code in Submit and OrderTicket would be helpful as well...

Submit 和 OrderTicket 中的代码也会有帮助......

You're reusing OrderTicket. I'd suspect that either you (or remoting itself) is batching calls out - probably in respect to # of connections/host limits - and picking up the last value of CacheId when it finally sends them along.

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

If you debug or Thread.Sleep the app, you're changing the timing so that the remoting call finishes before you assign a new CacheId.

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

Are you asyncing the remoting call? I'd think a sync call would block - but I'd check with a packet sniffer like Wireshark to be sure. Regardless, just changing to creating a new OrderTicket in each iteration would probably do the trick.

你在异步远程调用吗?我认为同步调用会阻塞 - 但我会使用像 Wireshark 这样的数据包嗅探器来确定。无论如何,在每次迭代中更改为创建一个新的 OrderTicket 可能会成功。

Edit: The question is notabout NewGuid being broken...so my previous answer has been removed.

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

回答by MusiGenesis

Thousands of developers use Guids in .NET. If Guid.NewGuid() had any tendency at all to get "stuck" on one value, the problem would have been encountered long ago.

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

The minor code changes are the sure culprit here. The fact that Thread.Sleep(which is less a red herring than a fish rotting in the sun) "fixes" your problem suggests that your properties are being set in some weird way that can't take effect until the loop stops blocking (either by ending or by Thread.Sleep). I'd even be willing to bet that the "minor change" was to reset all the properties from a separate thread.

小的代码更改是这里的罪魁祸首。事实上,了Thread.Sleep(这是少红鲱鱼比鱼在阳光下腐烂)“修复”你的问题表明你的属性是在一些奇怪的方式,直到循环停止封锁不能生效(任一组通过结束或通过 Thread.Sleep)。我什至愿意打赌“小改动”是从一个单独的线程重置所有属性。

If you posted some sample code, that would help.

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

回答by Gishu

I dont know the details of how GUIDs are generated.. yet. However currently my org. is breeding GUIDs at a rate that would put rabbits to shame. So I can vouch for the fact that GUIDs aren't broken.. yet.

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

  • Post the source code if possible.. or a clone repro app. Many times I find the act of creating that clone app to repro the problem shows me the issue.
  • The other approach would be to comment out "those minor changes". If that fixes the problem, you can then triangularize to find the offending line of code. Eye-ball the minor changes hard... I mean real Hard.
  • 如果可能,发布源代码......或克隆复制应用程序。很多时候我发现创建克隆应用程序来重现问题的行为向我展示了这个问题。
  • 另一种方法是注释掉“那些微小的变化”。如果这解决了问题,您可以三角化以找到有问题的代码行。眼球微小的变化很难......我的意思是真正的很难。

Do let us know how it goes... this sounds interesting.

请告诉我们进展如何……这听起来很有趣。

回答by Sam Saffron

My gut is telling me something along these lines is going on...

我的直觉告诉我一些事情正在发生……

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

Log the value of CacheId into a log file every time its called with a stack trace ... Maybe someone else is setting it.

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