5

私が読んだものはすべて、スレッドの中止が ThreadAbortException から終了する前に finally ブロックを実行すると主張しています。無期限にハングする可能性のあるサードパーティのコードを処理する方法を計画できるように、これを確認したかったのです。ただし、次のテストでは混乱します。

public void runTest(DateTime deadline)
{
    testThread = new Thread(() => 
    {
        try 
        {
            Console.WriteLine("test thread started at " + DateTime.Now.ToShortTimeString());
            while (true) { }
        }
        finally
        {
            Console.WriteLine("test thread entered FINALLY at " + DateTime.Now.ToShortTimeString());
            while (true) { }
        }
    });
    testThread.Start();
    while (testThread.IsAlive && deadline.Subtract(DateTime.Now).TotalSeconds > 0)
    {
        Console.WriteLine("main thread while loop " + DateTime.Now.ToShortTimeString());
        Thread.Sleep(10000);
    }
    if (testThread.IsAlive)
        testThread.Abort();
    Console.WriteLine("main thread after abort call " + DateTime.Now.ToShortTimeString());
}

これを実行したときにわかったのは、コンソールが finally ブロックに入ることについて言及していないことです。アプリケーションは、finally ブロックがまったくないかのように、.abort 呼び出しの後も続行します。私は何か間違ったことをしていますか?コンソールへの最終的な書き込みに到達する前に、finally ブロックへの制御パスを渡すべきではありませんか、それとも実行順序はまだ、finally が別のスレッドか何かにあるという事実の関数ですか?

4

3 に答える 3

5

ワーカー スレッド関数の finally ブロックは、メイン スレッドと並列なワーカー スレッドで実行されます。競合状態です。最終的にワーカー スレッドが実行されるか、アボート呼び出しが実行された後のメイン スレッド コードが先に実行されるかはわかりません。同期アボートが必要な場合は、次のようなものを配置する必要があります。

        if (testThread.IsAlive)
        {
            testThread.Abort();

            bool blnFinishedAfterAbort = testThread.Join(TimeSpan.FromMilliseconds(1000));
            if (!blnFinishedAfterAbort)
            {
                Console.WriteLine("Thread abort failed.");
            }
        }
        Console.WriteLine("main thread after abort call " + DateTime.Now.ToShortTimeString());

従来の例外処理が有効になっており ( http://msdn.microsoft.com/en-us/library/ms228965.aspxを参照)、 AppDomain_UnahandledExceptionイベント ハンドラーを指定した場合、ThreadAbortException によって実行がそのハンドラーのBEFOREに導かれることに注意してください。ワーカー スレッド関数の finally ブロック。これは、スレッドを中止する際に注意する必要がある、イライラする予期しない実行順序のもう 1 つの例です。

于 2013-08-01T19:28:16.297 に答える
2

finally通常はスキップしないでください。

finallyブロックが実行される前にコンソール アプリ (それが 1 つであると仮定) が終了している可能性があります (呼び出した後に待機がないためThread.Abort())。

Console.ReadLine()プログラムの最後に権利を置くとどうなりますか?

于 2013-08-01T19:26:48.733 に答える