Ошибка в конструкторе System.Random?

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 собственность говорит:

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.

Итак, если вы называетеRandom конструктор в течение этого периода в одну миллисекунду (после того, как системаint.MaxValue миллисекунды), это будет выбрасывать это исключение.

У кого-нибудь есть обходной путь? Для моего собственного кода я могу сделатьCreateRandom метод, который получаетTickCount значение и проверяет его наint.MinValue, Но что делать с кодом, который я не могу контролировать?

Я надеюсь, что команда RTL исправит это в .NET 4.0.

Обновление 2009/07/22: Команда BCL ответила на ошибку и сказала, что она исправлена в следующем выпуске.

 GManNickG18 июл. 2009 г., 20:56
Вау, хорошее расследование.
 Jim Mischel18 июл. 2009 г., 22:39
Об ошибке сообщили в Microsoft Connect.connect.microsoft.com/VisualStudio Ошибка № 475447.
 Jim Mischel18 июл. 2009 г., 23:00
На самом деле, мой отчет об ошибке # 475446. Кто-то еще сообщил об этом как 475447.
 n3rd18 июл. 2009 г., 20:55
Я надеюсь, что вы сделали сообщение об ошибке :)

Ответы на вопрос(1)

Решение Вопроса

try/catch и повторите попытку через миллисекунду, кажется, почти единственное, что вы можете сделать, пока эта ошибка не будет исправлена.

 19 июл. 2009 г., 01:18
Пока в глубине системных библиотек существует ошибка, которая приводит к возникновению исключений, когда их никогда не должно быть, что еще вы можете делать с другим кодом вне вашего контроля, к которому у вас нет источников, и который МОЖЕТ вызывать системная библиотека под вопросом? Если вы не можете переключиться на стек с открытым исходным кодом, где вы могли бы исправлять ошибки, как только вы их обнаружите, вы неизбежно окажетесь в милости поставщика проприетарного кода. try / catch - это почти единственное, что вы можете сделать, и оно определенно не идеально, но что еще?
 Jim Mischel18 июл. 2009 г., 22:05
Может быть. Но возьмите случай ConcurrentQueue.TryDequeue. Этот метод не должен генерировать исключения вообще. Теперь я должен обернуть все вызовы TryDequeue в блок try / catch. А как насчет кода, который я не знаю, использует Random?

Ваш ответ на вопрос