簡體   English   中英

ThreadAbortException

[英]ThreadAbortException

假設我們有一些類似的代碼在單獨的線程中運行:

private static void ThreadFunc() {
    ulong counter = 0;

    while (true) {

        try {
            Console.WriteLine( "{0}", counter++ );
        }
        catch (ThreadAbortException) {
            Console.WriteLine( "Abort!" );
        }

    }
}

調用Thread.Abort() ,是否有可能將異常引發到catch塊之外?

實際上是的, ThreadAbortException是特殊的。 即使您處理了它,它也會在try / catch / finally之后由CLR自動重新拋出。 (如注釋中所述,可以使用ResetAbort抑制它,但是到那時,代碼聞起來就像爛魚一樣。)

即使在try / catch / finally之外沒有明顯的可執行代碼,更不用說,循環的每次迭代都會在作用域之外停留一小段時間,因此中止可能發生在try塊之外。

除非您實際上是在catch塊中做某事,否則我只會嘗試一下/最后,不要擔心ThreadAbortException 有很多更好的方法可以在不使用Thread.Abort情況下中止線程,它不僅會在無法預測的點混亂地中斷您的代碼,而且還不能保證正常工作,因為如果您的線程當前正在調用某些非托管代碼,則該線程將不會中止直到控制權返回到托管代碼。

最好使用某種類型的同步原語,例如ManualResetEvent作為標記,告訴您的線程何時退出。 您甚至可以為此使用一個布爾字段,這是BackgroundWorker所做的。

是。 懷疑您在問,因為線程中斷僅在線程可能會以其他方式阻塞(或是否已經阻塞)時發生(例如,對於IO)。

沒有這樣的保證可以中止。 基本上,它可以在任何時間發生,盡管存在延遲中止區域(例如受約束的執行區域和catch / finally塊),只是記住了中止請求,而線程在退出該區域時中止了。

同步線程中止(即中止自己的線程)是相當安全的,但是異步中止(中止另一個線程)幾乎總是一個壞主意。 有關更多信息,請閱讀Joe Duffy的“ Windows上的並行編程”

編輯:正如下面的埃里克(Eric)所述,中止另一個線程也不能保證實際上有任何效果。 僅引用評論:

我會說, 如果線程退出該區域,則會中止該線程,強調Thread.Abort是完全不可靠的。 如果一個線程陷入無限循環而被中止,則該循環不會在該區域中中止。 這是Thread.Abort不好的另一個原因。 如果您不能依靠實際發生的預期效果,那為什么要調用該方法呢?

實際上, ThreadAbortException是特殊的,以防被CLR或Thread.Abort方法拋出。 比較輸出:

  • Joe Duffy的“ Windows並發編程”中的示例稍作修改(添加了Console.WriteLine)。 它通過Thread.CurrentThread.Abort引發異常:
    \ntry { try { Thread.CurrentThread.Abort(); } catch (ThreadAbortException) { Console.WriteLine("First"); //Try to swallow it. } //CLR automatically reraises the exception here . } catch (ThreadAbortException) { Console.WriteLine("Second"); Thread.ResetAbort(); //Try to swallow it again . } //The in - flight abort was reset , so it is not reraised again .\ntry { try { Thread.CurrentThread.Abort(); } catch (ThreadAbortException) { Console.WriteLine("First"); //Try to swallow it. } //CLR automatically reraises the exception here . } catch (ThreadAbortException) { Console.WriteLine("Second"); Thread.ResetAbort(); //Try to swallow it again . } //The in - flight abort was reset , so it is not reraised again . 
    輸出:
    \n 第一\n 第二\n
  • 修改前面的示例以使用不同的ThreadAbortException實例創建方法:
     try { try { // get non-public constructor var cstor = typeof(ThreadAbortException) .GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); // create ThreadAbortException instance ThreadAbortException ex = cstor.Invoke(null) as ThreadAbortException; // throw.. throw ex; } catch (ThreadAbortException) { Console.WriteLine("First"); } } catch (ThreadAbortException) { Console.WriteLine("Second"); Thread.ResetAbort(); } 
    輸出:
    \n 第一\n

似乎Thread的方法在內部調用本機代碼,這使引發的異常特定。

我不是100%的要求,但我想指出,您將永遠無法吞下ThreadAbortException

調用Abort方法銷毀線程時,公共語言運行庫將拋出ThreadAbortException ThreadAbortException是可以捕獲的特殊異常 ,但是它將在catch塊的末尾自動再次引發。

您是否在問是否可以使用try/catch在另一個線程中拋出的ThreadAbortException 如果這是您的問題,那么不會,您不能。

暫無
暫無

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

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