Błąd w konstruktorze System.Random?
TheSystem.Threading.ConcurrentQueue.TryDequeue
metoda rzuciła wyjątek innego dnia, który całkowicie mnie zaskoczył. Oto ślad stosu:
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()
Na początku myślałem, że problem polega na tymTryDequeueCore
zwanyRandom
konstruktor o złej wartości. Ale dalsze badania ujawniają toTryDequeueCore
wywołuje domyślny konstruktor. Wygląda na to, że błąd występuje wRandom
konstruktor:
.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
Jako dokumentacja dlaSystem.Environment.TickCount
właściwość mówi:
Wartość tej właściwości pochodzi z zegara systemowego i jest przechowywana jako 32-bitowa liczba całkowita ze znakiem. W konsekwencji, jeśli system działa nieprzerwanie, TickCount będzie się zwiększał od zera do Int32 .. ::. MaxValue przez około 24,9 dni, a następnie przeskoczy do Int32 .. ::. MinValue, która jest liczbą ujemną, a następnie zwiększa się do zera podczas następne 24,9 dni.
Więc jeśli zadzwonisz doRandom
konstruktor w okresie jednego milisekundy (po uruchomieniu systemu)int.MaxValue
milisekund), to rzuci ten wyjątek.
Czy ktoś ma obejście? Dla mojego własnego kodu mogę zrobićCreateRandom
metoda, która pobieraTickCount
wartość i sprawdza jąint.MinValue
. Ale co zrobić z kodem, nad którym nie mam kontroli?
Mam nadzieję, że zespół RTL naprawi to w .NET 4.0.
Aktualizacja 2009/07/22: Zespół BCL odpowiedział na błąd i powiedział, że został rozwiązany w następnej wersji.