1. 程式人生 > >如何終止執行緒的執行(C/C++)

如何終止執行緒的執行(C/C++)

想要終止執行緒的執行,可以使用以下方法: 
1、執行緒函式返回(最好使用該方法)。 
2、通過呼叫ExitThread函式,執行緒將自行撤消(最好不使用該方法)。 
3、同一個程序或另一個程序中的執行緒呼叫TerminateThread函式(應避免使用該方法)。 
4、ExitProcess和TerminateProcess函式也可以用來終止執行緒的執行(應避免使用該方法)。

下面將詳細介紹終止執行緒執行的方法:1-4,並說明執行緒終止執行時會出現何種情況:5。 

1、執行緒函式返回 
始終都應該將執行緒設計成這樣的形式,即當想要執行緒終止執行時,它們就能夠返回。這是確保所有執行緒資源被正確地清除的唯一辦法。 
如果執行緒能夠返回,就可以確保下列事項的實現: 
(1)線上程函式中建立的所有C++物件均將通過它們的撤消函式正確地撤消。 
(2)作業系統將正確地釋放執行緒堆疊使用的記憶體。 
(3)系統將執行緒的退出程式碼(線上程的核心物件中維護)設定為執行緒函式的返回值。 
(4)系統將遞減執行緒核心物件的使用計數。 

2、ExitThread函式 
可以讓執行緒呼叫ExitThread函式,以便強制執行緒終止執行: 
函式原型:
VOID ExitThread(DWORD dwExitCode); 
該函式將終止執行緒的執行,並導致作業系統清除該執行緒使用的所有作業系統資源。但是,C++資源(如C++類物件)將不被撤消。由於這個原因,最好從執行緒函式返回,而不是通過呼叫ExitThread來返回。 
當然,可以使用ExitThread的dwExitThread引數告訴系統將執行緒的退出程式碼設定為什麼。ExitThread函式並不返回任何值,因為執行緒已經終止執行,不能執行更多的程式碼。 
注意終止執行緒執行的最佳方法是讓它的執行緒函式返回。但是,如果使用本節介紹的方法,應該知道ExitThread函式是Windows用來撤消執行緒的函式。如果編寫C/C++程式碼,那麼決不應該呼叫ExitThread。應該使用Visual C++執行期庫函式_endthreadex。如果不使用Microsoft的Visual C++編譯器,你的編譯器供應商有它自己的ExitThread的替代函式。不管這個替代函式是什麼,都必須使用。 

3、TerminateThread函式 
呼叫TerminateThread函式也能夠終止執行緒的執行: 
函式原型:
BOOL TerminateThread( 
  HANDLE hThread, 
  DWORD dwExitCode); 
與ExitThread不同,ExitThread總是撤消呼叫的執行緒,而TerminateThread能夠撤消任何執行緒。hThread引數用於標識被終止執行的執行緒的控制代碼。當執行緒終止執行時,它的退出程式碼成為你作為dwExitCode引數傳遞的值。同時,執行緒的核心物件的使用計數也被遞減。 
注意TerminateThread函式是非同步執行的函式,也就是說,它告訴系統你想要執行緒終止執行,但是,當函式返回時,不能保證執行緒被撤消。如果需要確切地知道該執行緒已經終止執行,必須呼叫WaitForSingleObject或者類似的函式,傳遞執行緒的控制代碼。 
設計良好的應用程式從來不使用這個函式,因為被終止執行的執行緒收不到它被撤消的通知。執行緒不能正確地清除,並且不能防止自己被撤消。 
注意當使用返回或呼叫ExitThread的方法撤消執行緒時,該執行緒的記憶體堆疊也被撤消。但是,如果使用TerminateThread,那麼在擁有執行緒的程序終止執行之前,系統不撤消該執行緒的堆疊。Microsoft故意用這種方法來實現TerminateThread。如果其他仍然正在執行的執行緒要引用強制撤消的執行緒堆疊上的值,那麼其他的執行緒就會出現訪問違規的問題。如果將已經撤消的執行緒的堆疊留在記憶體中,那麼其他執行緒就可以繼續很好地執行。 
此外,當執行緒終止執行時, DLL通常接收通知。如果使用TerminateThread 強迫執行緒終止,DLL就不接收通知,這能阻止適當的清除。

4、在程序終止執行時撤消執行緒 
ExitProcess和TerminateProcess函式也可以用來終止執行緒的執行。差別在於這些執行緒將會使終止執行的程序中的所有執行緒全部終止執行。另外,由於整個程序已經被關閉,程序使用的所有資源肯定已被清除。這當然包括所有執行緒的堆疊。這兩個函式會導致程序中的剩餘執行緒被強制撤消,就像從每個剩餘的執行緒呼叫TerminateThread一樣。顯然,這意味著正確的應用程式清除沒有發生,即C++物件撤消函式沒有被呼叫,資料沒有轉至磁碟等等。 

5、執行緒終止執行時發生的操作 
當執行緒終止執行時,會發生下列操作: 
(1)執行緒擁有的所有使用者物件均被釋放。在Windows中,大多數物件是由包含建立這些物件的執行緒的程序擁有的。但是一個執行緒擁有兩個使用者物件,即視窗和掛鉤。當執行緒終止執行時,系統會自動撤消任何視窗,並且解除安裝執行緒建立的或安裝的任何掛鉤。其他物件只有在擁有執行緒的程序終止執行時才被撤消。 
(2)執行緒的退出程式碼從STILL_ACTIVE改為傳遞給ExitThread或TerminateThread的程式碼。 
(3)執行緒核心物件的狀態變為已通知。 
(4)如果執行緒是程序中最後一個活動執行緒,系統也將程序視為已經終止執行。 
(5)執行緒核心物件的使用計數遞減1。 
當一個執行緒終止執行時,在與它相關聯的執行緒核心物件的所有未結束的引用關閉之前,該核心物件不會自動被釋放。 
一旦執行緒不再執行,系統中就沒有別的執行緒能夠處理該執行緒的控制代碼。然而別的執行緒可以呼叫GetExitcodeThread來檢查由hThread標識的執行緒是否已經終止執行。如果它已經終止執行,則確定它的退出程式碼: 
函式原型:
BOOL GetExitCodeThread( 
  HANDLE hThread, 
  PDWORD pdwExitCode); 
退出程式碼的值在pdwExitCode指向的DWORD中返回。如果呼叫GetExitCodeThread時執行緒尚未終止執行,該函式就用STILL_ACTIVE識別符號(定義為0x103)填入DWORD。如果該函式執行成功,便返回TRUE。