ネットのThreadPoolスレッド上の例外
-
21-08-2019 - |
質問
の重複:?からの例外をキャッチする方法ThreadPool.QueueUserWorkItemする
<時間>私は独立したリモーティングの多数の.NET ThreadPoolの上に複数の代表者をキューイングしています自体は、複数のデータベースや他のオフラインリソースを呼び出すことを呼び出します。 ThreadPoolの上でこれらのコールをキューイングすることで、私はそれらを同時に実行し、全体的な待ち時間を最小限に抑えることができます。
private void CompleteAndQueuePayLoads(IEnumerable<UsagePayload> payLoads)
{
List<WaitHandle> waitHndls = new List<WaitHandle>();
foreach (UsagePayload uPyLd in payLoads)
{
ManualResetEvent txEvnt = new ManualResetEvent(false);
UsagePayload uPyLd1 = uPyLd ;
ThreadPool.QueueUserWorkItem(
delegate
{
if (!uPyLd1 .IsComplete)
// IEEDAL.GetPayloadReadings is long running DB call
try { IEEDAL.GetPayloadReadings(uPyLd1 ); }
catch (IEEAccessException iX)
{
log.Write(log.Level.Error,
"IEEWSDAL.CompleteAndQueuePayLoads " +
" Delegate Failed " +
iX.Message, iX);
txEvnt.Set();
throw; // this causes parent thread to crash!
// was going to try Thread.Abort next ...
// Thread.CurrentThread.Abort();
}
UsageCache.PersistPayload(uPyLd1 );
SavePayLoadToProcessQueueFolder(uPyLd1 );
txEvnt.Set();
});
waitHndls.Add(txEvnt);
}
util.WaitAll(waitHndls.ToArray()); //To waitone on > 64 waithandles
}
しかし、全体のバッチは、すなわち、親スレッドの出力だけですべての子スレッドが成功した場合は進行させることが必要であり、トランザクション処理する必要があります。
...私はそれが失敗したときにカスタム例外をスローするために子スレッドをコード化されていたが、私はこれらの例外は、親スレッドで「キャッチ」することができないとして、これは、親スレッドがクラッシュする原因となることを発見しました私はこの問題が発生した時にCLRによってスローUnHandledExceptionEventについて読んだことがあるが、私は成功をもとにすぐに下流の処理を制御するために、これらの子スレッドがキューに登録して生み出されたされている方法では、この例外を「ハンドル」する必要がありますtehの子threeadsの...私はこれについてどのように行くのですか?
解決
私は、この私の現在のプロジェクトで多くを行います。私が取ったアプローチは、デリゲートを取る自分のスケジューラを作ることだった私自身のキューに追加し、そしてなど、最後に同期を処理するためにそれらを実行します。
私はこのケースで使用していた「トリック」は、スレッドプールに直接デリゲートを呼び出すのではなく、デリゲートをラップし、より優雅に例外を処理する私のスケジューラでメソッドを呼び出すことではないことです。この方法で、実際、内部のメソッド呼び出しは、常に適切な(私にとって)方法で処理されます。
例外が発生した場合、、私のスケジューラに通知し、(素敵なボーナスです)今後の課題をスケジュール停止しますが、また、唯一の例外があったことを発信者に伝えるの世話をされます。
他のヒント
は、少なくとも1つの障害がCompleteAndQueuePayLoads関数のローカル変数内で発生したことをマークし、後で検討するために、可変例外/故障を追加することができます。
あなたは3.5の並列ライブラリの拡張に見えるかもしれません。あなたがしようとしている正確に何をするためにあなたのコードブロックにParallel.Invokeを使用することができます。