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将多个参数传递到线程;
(2)_beginthread 函数初始化某些 C 运行时库变量,在线程中若需要使用 C 运行时库。
3.终止线程
线程的终止有如下四种方式:
(1)线程函数返回;
(2)线程自身调用ExitThread 函数即终止自己,其原型为:
VOID ExitThread(UINT fuExitCode ); |
它将参数fuExitCode设置为线程的退出码。
注意:如果使用C/C++编写代码,我们应该使用C/C++运行时库函数_endthread (_endthreadex)终止线程,决不能使用ExitThread!
_endthread 函数对于线程内的条件终止很有用。例如,专门用于通信处理的线程若无法获取对通信端口的控制,则会退出。
(3)同一进程或其他进程的线程调用TerminateThread函数,其原型为:
BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode); |
该函数用来结束由hThread参数指定的线程,并把dwExitCode设成该线程的退出码。当某个线程不再响应时,我们可以用其他线程调用该函数来终止这个不响应的线程。
(4)包含线程的进程终止。
最好使用第1种方式终止线程,第2~4种方式都不宜采用。
4.挂起与恢复线程
当我们创建线程的时候,如果给其传入CREATE_SUSPENDED标志,则该线程创建后被挂起,我们应使用ResumeThread恢复它:
DWORD ResumeThread(HANDLE hThread); |
如果ResumeThread函数运行成功,它将返回线程的前一个暂停计数,否则返回0x FFFFFFFF。
对于没有被挂起的线程,程序员可以调用SuspendThread函数强行挂起之:
DWORD SuspendThread(HANDLE hThread); |
一个线程可以被挂起多次。线程可以自行暂停运行,但是不能自行恢复运行。如果一个线程被挂起n次,则该线程也必须被恢复n次才可能得以执行。