この質問を調査した結果: Rethrowing exception in Task doesn't make the Task to go to faulted state、理解できない非常に奇妙な動作に気付きましたThreadAbortException
。
今、私はそれThreadAbortException
が非常に特別な種類の例外であることを知っています. そして、それが言うとき、ドキュメントはそれについてかなり明確です:
ThreadAbortException
キャッチできる特別な例外ですが、catch
ブロックの最後で自動的に再び発生します。
シナリオ #1 : 文書化された動作。
static void Main(string[] args)
{
try
{
Thread.CurrentThread.Abort();
}
catch (Exception tae)
{
Console.WriteLine("caught exception: " + tae.GetType().Name);
}
Console.WriteLine("will never be reached");
}
予想どおり、ThreadAbortException
は自動的に再スローされ、次の出力が得られます。
caught exception: ThreadAbortException
シナリオ #2 : 興味深いのは、catch
ブロックで別の例外をスローすることにしたときです。
static void Main(string[] args)
{
try
{
Thread.CurrentThread.Abort();
}
catch (Exception tae)
{
Console.WriteLine("caught exception: " + tae.GetType().Name);
throw new ApplicationException(); // will ThreadAbortException take precedence?
}
Console.WriteLine("will never be reached");
}
この場合、 がスローされたにもかかわらず、文書化された動作が確実に保持されるようにApplicationException
、が再スローされると想定しました。ThreadAbortException
驚いたことに、これが結果の出力です。
caught exception: ThreadAbortException
Unhandled Exception: System.ApplicationException: Error in the application.
at ConsoleApplication1.Program.Main(String[] args) in C:\projects\ConsoleApplication1\Program.cs:line 193
はApplicationException
実際に交換して、投げられるのを防ぎThreadAbortException
ましたか?!?
シナリオ #3 : 最後に、さらに興味深いことに、既存の例外処理をもう 1 つのtry-catch
レイヤーでラップします。
static void Main(string[] args)
{
try
{
try
{
Thread.CurrentThread.Abort();
}
catch (Exception tae)
{
Console.WriteLine("caught exception: " + tae.GetType().Name);
throw new ApplicationException();
}
}
catch (Exception outerEx)
{
Console.WriteLine("caught outer exception: " + outerEx.GetType().Name);
}
Console.WriteLine("will never be reached");
}
今、私は何を期待すべきかよくわかりません。外側のcatch
ブロックでキャッチされるのはどの例外ですか? でしょうApplicationException
か?もしそうなら、それは私が例外を飲み込み、実際にwill never be reached
文字列を出力することができるということですか?
これは実際の出力です:
caught exception: ThreadAbortException
caught outer exception: ApplicationException
catch
上記の出力から、外側のブロックが実際に をキャッチしているように見えますApplicationException
。しかし、その catch
ブロックの終わりまでにThreadAbortException
、突然、何もないところから再び現れて、再び投げ出されますか?
質問: 誰かがシナリオ #2 と #3 を説明し、調整してもらえますか? シナリオ 2 でThreadAbortException
、予期せず別の例外に置き換えられたように見えるのはなぜですか? ThreadAbortException
しかし、シナリオ #3 では、ずっとそこにいたように見えますか? これはどのように起こっていますか?この動作はどこかに文書化されていますか?