一. 产生一个线程
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性,NULL表示使用缺省值。
DWORD dwStackSize, // 线程的堆栈,0 表示用缺省大小: 1M
LPTHREAD_START_ROUTINE lpStartAddress, // 线程的起始地址,这里是一个函数指针
LPVOID lpParameter, // 上面线程函数的参数
DWORD dwCreationFlags, // 允许你产生一个暂时挂起的线程,默认是"立即执行"
LPDWORD lpThreadId // 新线程的ID会被传回到这里
);
//返回值:如果成功,传回一个handle,表示一个新线程;否则返回一个FALSE
CreateThread()返回两个值,用以识别这个新线程。一个值是返回值 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()里创建的其它线程都将被迫结束。