System.Threading.ConcurrentQueue.TryDequeue
方法最近抛出了一个异常,让我感到完全意外。下面是堆栈跟踪:
System.OverflowException: Negating the minimum value of a twos complement number is invalid.
at System.Math.AbsHelper(Int32 value)
at System.Random..ctor(Int32 Seed)
at System.Threading.Collections.ConcurrentQueue`1.TryDequeueCore(T& result)
at System.Threading.Collections.ConcurrentQueue`1.TryDequeue(T& result)
at MyProgram.ThreadProc() in c:\MyProgram\Main.cs:line 118
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
起初我以为问题出在TryDequeueCore
调用了错误值的Random
构造函数上。但进一步的调查发现TryDequeueCore
调用的是默认构造函数。看起来错误出在Random
构造函数中:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call int32 System.Environment::get_TickCount()
IL_0006: call instance void System.Random::.ctor(int32)
IL_000b: ret
} // end of method Random::.ctor
正如System.Environment.TickCount
属性的文档所述:
这个属性的值是从系统计时器派生出来的,并存储为32位有符号整数。因此,如果系统连续运行,TickCount将从零递增到大约24.9天的Int32..::.MaxValue,然后跳到Int32..::.MinValue,这是一个负数,然后在接下来的24.9天内递增回到零。
因此,在该一毫秒时间段内(系统启动了int.MaxValue
毫秒后),如果调用Random
构造函数,它将抛出此异常。
有人有解决方法吗?对于我的代码,我可以创建一个CreateRandom
方法获取TickCount
值并检查它是否为int.MinValue
。但对于我无法控制的代码怎么办?
我希望RTL团队在.NET 4.0中修复这个问题。
更新2009/07/22:BCL团队回应了该BUG并表示已经在下一个版本中解决了这个问题。