title: Bug in System.Random constructor?
body: <p>The <code>System.Threading.ConcurrentQueue.TryDequeue</code> method threw an exception the other day that took me totally by surprise.  Here's the stack trace:</p>
  
  <pre><code>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&amp; result)
     at System.Threading.Collections.ConcurrentQueue`1.TryDequeue(T&amp; 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()
  </code></pre>
  
  <p>At first I thought the problem was that <code>TryDequeueCore</code> called the <code>Random</code> constructor with a bad value.  But further investigation reveals that <code>TryDequeueCore</code> calls the default constructor.  It looks to me like the error is in the <code>Random</code> constructor:</p>
  
  <pre><code>.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
  </code></pre>
  
  <p>As the documentation for the <code>System.Environment.TickCount</code> property says:</p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>
  
  <p>So, if you call the <code>Random</code> constructor during that one-millisecond period (after the system has been up for <code>int.MaxValue</code> milliseconds), it's going to throw this exception.</p>
  
  <p>Does anybody have a workaround?  For my own code, I can make a <code>CreateRandom</code> method that gets the <code>TickCount</code> value and checks it for <code>int.MinValue</code>.  But what to do about code that I have no control over?</p>
  
  <p>I hope the RTL team fixes this in .NET 4.0.</p>
  
  <p>Update 2009/07/22: The BCL Team responded to the bug and said that it has been resolved for the next release.</p>