2.創建線程
進程的主線程由操作系統自動生成,Win32提供了CreateThread API來完成用戶線程的創建,該API的原型為:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//Pointer to a SECURITY_ATTRIBUTES structure SIZE_T dwStackSize, //Initial size of the stack, in bytes. LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, //Pointer to a variable to be passed to the thread DWORD dwCreationFlags, //Flags that control the creation of the thread LPDWORD lpThreadId //Pointer to a variable that receives the thread identifier ); |
如果使用C/C++語言編寫多線程應用程序,一定不能使用操作系統提供的CreateThread API,而應該使用C/C++運行時庫中的_beginthread(或_beginthreadex),其函數原型為:
uintptr_t _beginthread( void( __cdecl *start_address )( void * ), //Start address of routine that begins execution of new thread unsigned stack_size, //Stack size for new thread or 0. void *arglist //Argument list to be passed to new thread or NULL ); uintptr_t _beginthreadex( void *security,//Pointer to a SECURITY_ATTRIBUTES structure unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, unsigned initflag,//Initial state of new thread (0 for running or CREATE_SUSPENDED for suspended); unsigned *thrdaddr ); |
_beginthread函數與Win32 API 中的CreateThread函數類似,但有如下差異:
(1)通過_beginthread函數我們可以利用其參數列表arglist將多個參數傳遞到線程;
?。?)_beginthread 函數初始化某些 C 運行時庫變量,在線程中若需要使用 C 運行時庫。
3.終止線程
線程的終止有如下四種方式:
(1)線程函數返回;
?。?)線程自身調用ExitThread 函數即終止自己,其原型為:
VOID ExitThread(UINT fuExitCode ); |
它將參數fuExitCode設置為線程的退出碼。
注意:如果使用C/C++編寫代碼,我們應該使用C/C++運行時庫函數_endthread (_endthreadex)終止線程,決不能使用ExitThread!
_endthread 函數對于線程內的條件終止很有用。例如,專門用于通信處理的線程若無法獲取對通信端口的控制,則會退出。
?。?)同一進程或其他進程的線程調用TerminateThread函數,其原型為:
BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode); |
該函數用來結束由hThread參數指定的線程,并把dwExitCode設成該線程的退出碼。當某個線程不再響應時,我們可以用其他線程調用該函數來終止這個不響應的線程。
?。?)包含線程的進程終止。
最好使用第1種方式終止線程,第2~4種方式都不宜采用。
4.掛起與恢復線程
當我們創建線程的時候,如果給其傳入CREATE_SUSPENDED標志,則該線程創建后被掛起,我們應使用ResumeThread恢復它:
DWORD ResumeThread(HANDLE hThread); |
如果ResumeThread函數運行成功,它將返回線程的前一個暫停計數,否則返回0x FFFFFFFF。
對于沒有被掛起的線程,程序員可以調用SuspendThread函數強行掛起之:
DWORD SuspendThread(HANDLE hThread); |
一個線程可以被掛起多次。線程可以自行暫停運行,但是不能自行恢復運行。如果一個線程被掛起n次,則該線程也必須被恢復n次才可能得以執行。