3

この質問を調査した結果: 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 では、ずっとそこにいたように見えますか? これはどのように起こっていますか?この動作はどこかに文書化されていますか?

4

1 に答える 1