The System.Threading.ConcurrentQueue.TryDequeue
method threw an exception the other day that took me totally by surprise. Here's the stack trace:
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()
At first I thought the problem was that TryDequeueCore
called the Random
constructor with a bad value. But further investigation reveals that TryDequeueCore
calls the default constructor. It looks to me like the error is in the Random
constructor:
.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
As the documentation for the System.Environment.TickCount
property says:
The value of this property is derived from the system timer and is stored as a 32-bit signed integer. Consequently, if the system runs continuously, TickCount will increment from zero to Int32..::.MaxValue for approximately 24.9 days, then jump to Int32..::.MinValue, which is a negative number, then increment back to zero during the next 24.9 days.
So, if you call the Random
constructor during that one-millisecond period (after the system has been up for int.MaxValue
milliseconds), it's going to throw this exception.
Does anybody have a workaround? For my own code, I can make a CreateRandom
method that gets the TickCount
value and checks it for int.MinValue
. But what to do about code that I have no control over?
I hope the RTL team fixes this in .NET 4.0.
Update 2009/07/22: The BCL Team responded to the bug and said that it has been resolved for the next release.
try
/catch
and retry a millisecond later seems just about the only thing you can do until this bug does get fixed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With