2009-07-18 7 views
20

System.Threading.ConcurrentQueue.TryDequeueメソッドは、驚いて私を完全に連れて行った先日例外を投げた。ここでは、スタックトレースがあります:まずSystem.Randomコンストラクタのバグ?

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日間.. ::。MaxValueをゼロからのInt32 に増加します 、その後のInt32にジャンプ.. ::。 負の数であるMinValueプロパティ、その後、インクリメント次の24.9日間に をゼロに戻します。

あなたは(システムがint.MaxValueミリ秒アップされた後)は1ミリ秒の期間中にRandomコンストラクタを呼び出すのであれば、この例外をスローするだろう。

誰にも回避策がありますか?私のコードではCreateRandomメソッドを作成してTickCountの値を取得し、int.MinValueの値をチェックします。しかし、私が制御できないコードについてはどうすればいいですか?

RTLチームが.NET 4.0でこれを修正してくれることを願っています。

更新2009/07/22:BCLチームがバグに応答し、次のリリースで解決されたと言いました。

+2

あなたはバグレポートを作って欲しいと思っています:) – n3rd

+2

うわー、素晴らしい調査。 – GManNickG

+1

Microsoft Connectで報告されているバグ。 https://connect.microsoft.com/VisualStudio バグ#475447。 –

答えて

4

try/catchこのバグが修正されるまで、後でミリ秒後に再試行することができます。

+0

おそらく。しかし、ConcurrentQueue.TryDequeueの場合を取る。このメソッドは、例外をスローするものではありません。 TryDequeueへのすべての呼び出しをtry/catchブロックでラップする必要があります。そして、私が知らないコードについて、ランダムを使用するのはどうですか? –

+0

システムライブラリの深いところでは、決してあってはならない例外がスローされるバグがあります。コントロールの外にある他のコードで何ができますか?ソースがなく、問題のシステムライブラリですか?一度見つけたエラーを修正できるオープンソースのスタックに切り替えることができない限り、あなたは必然的に独自のコードサプライヤの慈悲に晒されています。 try/catchはあなたができる唯一のことであり、完璧ではありませんが、他に何がありますか? –