簡體   English   中英

ThreadAbortException最終可以跳過嗎?

[英]Can ThreadAbortException skip finally?

我讀過的所有內容聲稱線程中止將在從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塊。 應用程序在.abort調用之后繼續,好像根本沒有finally塊。 難道我做錯了什么? 在到達最終寫入控制台之前,不應該控制傳遞給finally塊,還是執行順序仍然是最終在單獨的線程中的事實的函數?

文檔說ThreadAbortException是一個可以捕獲的特殊異常,但它會在catch塊的末尾自動再次引發。 引發此異常時,運行時會在結束線程之前執行所有finally塊。 因為線程可以在finally塊中執行無限制計算或調用Thread.ResetAbort來取消中止,所以無法保證線程將永遠結束。

我很確定您的線程被轉儲,因為您退出方法並丟失對它的引用,因此它被垃圾收集器收集。 嘗試將testThread變量作為類的字段成員,看看會發生什么。

那個,或者你有一個競爭條件,因為線程並行運行:主線程在spun-up測試線程可以輸出finally數據之前完成(例外是昂貴的,需要時間來達到catch或finally塊)。

工作線程函數中的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塊 這只是在中止線程時應該注意的令人沮喪和意外的執行順序的另一個例子。

通常不應該跳過finally

控制台應用程序(假設它是一個)可能在finally塊運行之前退出(因為在調用Thread.Abort()之后沒有等待)。

如果你在程序結束時放置Console.ReadLine()會發生什么?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM