2012-06-13 101 views
11

我在C#中使用了一個線程,我將IsBackground屬性設置爲true。線程在循環中運行一些代碼,直到應用程序關閉。當應用程序關閉時,線程也會停止執行(因爲我設置了IsBackground = true)。當應用程序關閉時,我可以檢測到應用程序何時終止了後臺線程?

應用程序如何殺死線程?它似乎不通過調用中止,因爲我沒有得到一個ThreadAbortException。它發生在幕後嗎?我想在循環的最後一部分做一些回滾。

我知道我可以在線程中自己調用abort,但是我想知道應用程序如何關閉我的後臺線程,以及如果我可以從線程內部對其進行響應。我知道我可以訂閱Application.ApplicationExit事件,但我在一個服務和一個winform中運行這個代碼,我更喜歡在循環內捕獲一個異常,所以我能夠在finally語句中回滾。

+0

您可以使其成爲前臺線程並創建手動關閉線程的'全局'應用程序關閉方案。 – CodingBarfield

+0

你看過[AppDomain.ProcessExit](http://msdn.microsoft.com/en-us/library/system.appdomain.processexit.aspx)事件嗎? – Botz3000

+0

所以你們都說它發生在幕後,除了創建這些定製解決方案外,我無法對此做出反應? –

回答

5

看來,它不通過調用中斷,因爲我沒有得到一個ThreadAbortException

它確實做到這一點,在CLR有兩種方法來終止線程。通過Thread.Abort()調用的「正常」方式,該線程可以看到一個ThreadAbortException。但也有一個粗魯的墮胎,工作原理是一樣的。但是減去TAE並且沒有最後的塊執行。你無法觀察它。

+0

啊哈..感謝你整理出來。我在這個 –

+0

找不到任何文檔在MSDN上它是錯誤的嗎? http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception。aspx 當公共語言運行庫(CLR)在託管可執行文件中的所有前臺線程結束後都會停止後臺線程時,它不會使用Thread.Abort。因此,不能使用ThreadAbortException檢測CLR何時終止後臺線程。 – Eldar

+0

我沒有看到該MSDN文章和此答案之間的任何差異。粗魯中止可以由應用程序代碼觸發,但您需要AppDomain.Unload或Environment.Exit,通常不是任何人首先想到的作爲中止線程的方式的方法:) –

1

當操作系統將處理器分配給thread時,開始thread進入運行狀態(即開始執行)。當一個啓動線程第一次接收到一個處理器併成爲一個正在運行的線程時,線程執行它的ThreadStart delegate,它指定了線程在其生命週期中將執行的操作。當程序創建一個新的線程時,程序將線程的ThreadStart delegate指定爲線程構造函數的參數。

正在運行的線程在ThreadStart delegate終止時進入Stopped (or Dead)狀態。在你的情況下,你的主線程終止。所以,你的ThreadStart delegate對象不會保留在內存中。當沒有對線程對象的引用時,垃圾收集器可以從內存中刪除線程對象。

+0

感謝您對此的一個很好的解釋。 我結束了使用Botz3000建議的AppDomain.ProcessExit事件。然後,當這個事件被引發時,我可以調用thread.Abort()。它似乎運作良好。 –

+0

這個答案是不正確的。 GC收集它後不會中止放棄的後臺線程。無論您對託管線程對象有多強的引用,它都會被運行時強制中止。見漢斯的解釋答案。 – Josh

+0

@JoshEinstein:可能你是對的,但漢斯沒有解釋CLR如何異常中止線程....你能解釋一下嗎? – Talha

相關問題