解析C/C++中如何終止線程的運行

來源:互聯網
上載者:User

想要終止線程的運行,可以使用以下方法:
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。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.