一. 产生一个线程
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性,NULL表示使用缺省值。 DWORD dwStackSize, // 线程的堆栈,0 表示用缺省大小: 1M LPTHREAD_START_ROUTINE lpStartAddress, // 线程的起始地址,这里是一个函数指针 LPVOID lpParameter, // 上面线程函数的参数 DWORD dwCreationFlags, // 允许你产生一个暂时挂起的线程,默认是"立即执行" LPDWORD lpThreadId // 新线程的ID会被传回到这里 ); //返回值:如果成功,传回一个handle,表示一个新线程;否则返回一个FALSECreateThread()返回两个值,用以识别这个新线程。一个值是返回值 HANDLE,大部分与线程有关的API函数都需要它;第二个值是线程ID,但是你不可以根据线程 ID 来获得其 handle。
二. 释放核心对象
BOOL CloseHandle( HANDLE hObject // handle to object ); //返回值:如果成功返回TRUE,否者返回FASLE
所有的核心对象都保持了一个引用计数,以记录有多少个 handles 对应到此对象。当你调用 CloseHandle()时,引用计数便递减 1。
线程对象默认引用计数是 2,当你调用 CloseHandle()时,引用计数便递减 1,当线程结束时,引用计数再减 1,如果值变成 0,对象会自动被操作系统销毁。
其实调用这个函数,只不过表示希望自己和此核心对象不再有任何瓜葛。CloseHandle()唯一做的事情就是把引用计数减 1。
三. 线程结束代码
BOOL GetExitCodeThread( HANDLE hThread, // CreateThread()返回的线程 handle LPDWORD lpExitCode // 指向一个DWORD,用以接受结束代码 ); //返回值:如果成功返回TRUE,否者返回FASLE
如果线程已结束,那么结束码会放在lpExitCode中,如果线程尚未结束,lpExitCode 的值为 STILL_ACTIVE。
要注意,千万不要用这个函数的返回值来判断线程是运行还是结束。
四. 结束一个线程
VOID ExitThread( DWORD dwExitCode // 指定此线程的结束码 ); //没有返回值注意,任何代码若放在此行之下,都不会被执行。
五. 示例代码
#define WIN32_LEAN_AND_MEAN #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <conio.h> DWORD WINAPI ThreadFunc(LPVOID); int main() { HANDLE hThrd1; HANDLE hThrd2; DWORD exitCode1 = 0; DWORD exitCode2 = 0; DWORD threadId; hThrd1 = CreateThread(NULL, 0, ThreadFunc, (LPVOID)1, 0, &threadId ); if (hThrd1) printf("Thread 1 launched\n"); hThrd2 = CreateThread(NULL, 0, ThreadFunc, (LPVOID)2, 0, &threadId ); if (hThrd2) printf("Thread 2 launched\n"); // Keep waiting until both calls to // GetExitCodeThread succeed AND // neither of them returns STILL_ACTIVE. // This method is not optimal - we'll // see the correct way in Chapter 3. for (;;) { printf("Press any key to exit..\n"); getch(); GetExitCodeThread(hThrd1, &exitCode1); GetExitCodeThread(hThrd2, &exitCode2); if ( exitCode1 == STILL_ACTIVE ) puts("Thread 1 is still running!"); if ( exitCode2 == STILL_ACTIVE ) puts("Thread 2 is still running!"); if ( exitCode1 != STILL_ACTIVE && exitCode2 != STILL_ACTIVE ) break; } CloseHandle(hThrd1); CloseHandle(hThrd2); printf("Thread 1 returned %d\n", exitCode1); printf("Thread 2 returned %d\n", exitCode2); return EXIT_SUCCESS; } /* * Take the startup value, do some simple math on it, * and return the calculated value. */ DWORD WINAPI ThreadFunc(LPVOID n) { Sleep((DWORD)n*1000*2); return (DWORD)n * 10; }说明:
主线程结束会使得程序中的所有线程都被迫结束,其他线程没有机会做清理工作。比如,如果 main() 结束了,那么在main()里创建的其它线程都将被迫结束。