我们有一个应用程序为我们的某个服务生成模拟数据以进行测试。每个数据项都有一个唯一的Guid。但是,当我们在模拟器的一些次要代码更改后运行测试时,它生成的所有对象都具有相同的Guid。
创建了一个数据对象,然后是一个for循环,其中修改了对象的属性,包括一个新的唯一Guid,并通过远程处理将其发送到服务(serializable,而不是marshal-by-ref,如果这就是你的想法,循环再做一遍等等。
如果我们在循环中放入一个小的Thread.Sleep(...),它会生成唯一的id。我认为这是一个红鲱鱼。我创建了一个测试应用程序,它刚刚创建了一个guid,并且没有一个副本。
我的理论是IL的优化方式导致了这种行为。但足够我的理论。你怎么看?我愿意接受测试的建议和方法。
更新:我的问题似乎有很多混乱,所以让我澄清一下。我不认为NewGuid()被破坏了。显然它有效。没关系!但是某处有一个bug会导致NewGuid(): 1)在我的循环中只调用一次 2)每次在我的循环中调用,但只分配一次 3)我还没有想到的其他东西
这个错误可能出现在我的代码中(可能是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
}
答案 0 :(得分:21)
提交是否进行异步调用,或者票证对象是否在任何阶段进入另一个线程。
在代码示例中,您将重用相同的对象。如果提交在短暂延迟后在后台线程中发送票证(并且不复制),该怎么办?当您更改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));
答案 1 :(得分:6)
成千上万的开发人员在.NET中使用Guids。如果Guid.NewGuid()有任何倾向于“卡住”一个值,很久以前就会遇到这个问题。
次要代码更改是这里的罪魁祸首。事实上Thread.Sleep(不是红色鲱鱼比在阳光下腐烂的鱼)“修复”你的问题表明你的属性被设置为某种奇怪的方式,直到循环停止阻塞才能生效(通过结束或通过Thread.Sleep)。我甚至愿意打赌,“小改动”是从一个单独的线程重置所有属性。
如果您发布了一些示例代码,那将会有所帮助。
答案 2 :(得分:3)
这是您代码中的错误。如果你设法生成多个guid,那么这是最可能的解释。你的问题就在于:“当我们在模拟器的一些小代码更改后运行测试 它生成的所有对象都具有相同的Guid”
答案 3 :(得分:2)
请参阅此article,了解如何创建Guid。
这种艺术来自This回答。
如果你过快地创建GUID并且时钟没有向前移动那么这就是为什么你会得到一些同样的原因。但是当你把睡眠放进去时,因为时钟已经移动了。
答案 4 :(得分:2)
Submit和OrderTicket中的代码也很有用......
您正在重复使用OrderTicket。我怀疑你(或远程本身)正在批处调用 - 可能是关于连接数/主机限制 - 并在最终发送它们时获取CacheId的最后一个值。
如果您调试或Thread.Sleep应用程序,您正在更改时间,以便在分配新的CacheId之前完成远程处理调用。
您是否正在拨打远程电话?我认为同步调用会阻塞 - 但我会检查一下像Wireshark这样的数据包嗅探器。无论如何,只需改变在每次迭代中创建一个新的OrderTicket就可以了。
编辑:关于NewGuid被破坏的问题不 ...所以我之前的答案已被删除。
答案 5 :(得分:1)
我不知道如何生成GUID的细节。但是目前我的组织。是以一种让兔子感到羞耻的速度繁殖GUIDs。所以我可以保证 GUID没有被破坏...... 。
让我们知道它是怎么回事......这听起来很有趣。
答案 6 :(得分:0)
我的直觉告诉我这些事情正在发生......
class OrderTicket
{
Guid CacheId {set {_guid = new Guid("00000000-0000-0000-0000-");}
}
每次使用堆栈跟踪调用时,将CacheId的值记录到日志文件中......也许其他人正在设置它。