首先要关联头文件Window.h,需要使用Windows系统的底层方法
//定义一个方法,弹出一个消息框
//该方法返回值为DWORD WINAPI类型,参数为一个空指针
DWORD WINAPI run(void * p) {
MessageBox(0, "多线程测试", "信息", 0);
}
//main方法中开启线程
int main(void) {
//使用_beginthread方法开启线程,让开启的线程执行run方法
_beginthread(run, 0, NULL);
//使用CreateThread方法开启线程,让开启的线程执行run方法
CreateThread(NULL, 0, run, NULL, 0, NULL);
system("pause");
return 0;
}
执行程序,结果如下,同时弹出两个消息框(不使用多线程时必须关闭一个消息框才会弹出下一个)
_beginthread方法和CreateThread各开启了一个线程,两个线程均弹出了一个消息框
uintptr_t _beginthread( // NATIVE CODE
void( __cdecl *start_address )( void * ),
unsigned stack_size,
void *arglist
);
参数 | 含义 |
---|---|
start_address | 启动开始执行新线程的例程的地址,是一个指针类型的数据,可以使用函数名做为参数,因为函数名就是一个指针 |
stack_size | 用于设置新开启的线程的线程栈的大小(每个线程都有一个私有的线程栈),如果设置为0,则会按照默认大小创建 |
arglist | 要传递到新线程的参数列表或 NUL |
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
参数 | 含义 |
---|---|
lpThreadAttributes | 用于设置线程安全级别 |
dwStackSize | 用于设置新开启的线程的线程栈的大小(每个线程都有一个私有的线程栈),如果设置为0,则会按照默认大小创建 |
lpStartAddress | 启动开始执行新线程的例程的地址,是一个指针类型的数据,可以使用函数名做为参数,因为函数名就是一个指针 |
dwCreationFlags | 指注册表的键值,设置为0即可,程序执行时编译器会根据系统自动查找注册表的键值 |
lpThreadId | 线程ID |
创建线程的两个方法中,均有一个参数用来指定新开启的线程要执行的方法,该方法返回一个DWORD WINAPI类型的返回值,根据DWORD WINAPI的定义,可以看出是一个long类型的数据
typedef unsigned long DWORD;
#define APIENTRY WINAPI
DWORD全称Double Word,是指注册表的键值,每个word为2个字节的长度,DWORD双字即为4个字节
设备驱动程序和服务的许多参数都是DWORD类型,以二进制、十六进制或十进制格式显示在注册表编辑器中
DWORD根据操作系统的不同,被定义成了不同的长度,比如vs8(xp)中,DWORD被定义成了如下的类型:typedef unsigned long DWORD; 而unsigned long 的长度则是4个字节即32位,如果是在64位的操作系统中,这个长度可能会更长,取决于当前操作系统以及开发环境
一个HANDLE类型的数据
上述两个创建线程的方法都返回一个HANDLE WINAPI类型的参数,HANDLE 的中文含义是把手,操纵,专业术语为句柄。
HANDLE是Windows操作系统中的一个概念。在Windows程序中,有各种各样的资源(窗口、图标、光标等),系统在创建这些资源时会为它们分配内存,并返回标示这些资源的标示号,即句柄。
指的是一个核心对象在某一个进程中的唯一索引,而不是指针。由于地址空间的限制,句柄所标识的内容对进程是不可见的,只能由操作系统通过进程句柄列表来进行维护。
每个进程都要创建一个句柄列表,这些句柄指向各种系统资源,比如信号量,线程,和文件等,进程中的所有线程都可以访问这些资源。
void main() {
printf("测试第一种线程结束方法");
system("pause");
//_beginthread(endThread_1,0, NULL);
printf("测试第二种线程结束方法");
system("pause");
//CreateThread(NULL, 0, endThread_2, NULL, 0, NULL);
printf("测试第三种线程结束方法");
system("pause");
HANDLE handle = CreateThread(NULL, 0, endThread_3, NULL, 0, NULL);
Sleep(3000);
//外部退出线程的方法,参数为需要被结束的线程的HANDLE值
TerminateThread(handle , 0 );
system("pause");
}
DWORD WINAPI endThread_1(void *p) {
int i = 1;
while (1) {
printf("\n%d\n", i);
Sleep(1000);
i++;
if (i == 10) {
//内部退出线程的方法,线程执行到该语句后结束
_endthread();
}
}
}
DWORD WINAPI endThread_2(void *p) {
int i = 1;
while (1) {
printf("\n%d\n", i);
Sleep(1000);
i++;
if (i == 10) {
//内部退出线程的方法,线程执行到该语句后结束
ExitThread(0);
}
}
}
DWORD WINAPI endThread_3(void *p) {
int i = 1;
while (1) {
printf("\n%d\n", i);
Sleep(1000);
i++;
}
}
前两种线程结束方法,在开始执行后打印数字,当打印到数字10时停止,线程结束。第三种方法在开始执行后打印数字,打印到数字3时停止打印
void _endthread( void );
VOID WINAPI ExitThread(
_In_ DWORD dwExitCode
);
dwExitCode参数是,线程的退出代码,输入0即可
BOOL WINAPI TerminateThread(
_Inout_ HANDLE hThread,
_In_ DWORD dwExitCode
);
hThread参数是线程的HANDLE值
dwExitCode参数是,线程的退出代码,输入0即可