什么是进程线程?
进程是正在运行的程序的实例。一个进程至少有一个线程,一个进程中可以并发多个线程,每条线程同时执行不同的任务
HANDLE CreateThread(
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize, //线程堆栈大小
[in] LPTHREAD_START_ROUTINE lpStartAddress, //线程的执行函数
[in, optional] __drv_aliasesMem LPVOID lpParameter, //线程参数
[in] DWORD dwCreationFlags, //为0则线程创建完毕后立即调度
[out, optional] LPDWORD lpThreadId //线程ID
);
Tips:
1.CreateThread函数仅用于创建线程,它本身并不执行任何功能,其第三个参数才是指定线程执行函数的地址,通常为一个全局变量,而函数名称即为全局变量
2.第五个参数的值为0则在线程创建完毕后立即进行调度,但是并不代表这个线程百分百就会立即执行。因为系统总共就那么多CPU,一旦没有空余CPU,即使这个值传0,线程也不能立即执行。要等待系统分给它一个CPU,它才可以跑得动
另外,如果传入的值是CREATE_SUSPENDED,则线程创建后立即挂起,需调用ResumeThread函数后该线程方可执行
void MyTest()
{
int num1 = 2;
//返回值是线程句柄
HANDLE hThread = CreateThread(
NULL, //安全属性,通常为NULL
0, //参数,用于设定线程可以将多少地址空间用于它自己的堆栈
//每个线程都拥有它自己的堆栈
ThreadProc, //参数,用于指明想要新线程执行的线程函数地址
(void*)num1, //传入线程函数的参数
//既可以是数字,也可以是个指向某一结构的指针
0, //若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
NULL //线程ID
);
::CloseHandle(hThread);
}
我们可以看到,在MyTest函数里面调用了CloseHandle来关闭线程,但是这并不代表这个线程就没了,只是把当前线程的编号(句柄)处理掉了。如果我们之后再想调用这个进程,可以通过其他函数再赋给这个线程一个句柄
但是这样的话线程还能停下吗?显然是可以的
DWORD WINAPI ThreadProc(
LPVOID lpParameter
)
{
int p = (int)lpParameter;
for (int i = 0; i < 1000; i++)
{
Sleep(1000);
printf("------%d-------\n",p);
}
return 0;
}
就拿当前程序来说,我们创建的线程调用的执行函数ThreadProc是一个循环1000次的输出,当它循环结束退出后,这个线程就跑完了
线程传参
通过上面的CreateThread函数我们知道,第四个参数就是我们想要传给线程执行函数的参数,那么怎么传参呢?一共有两种方法,一种是和上面的代码一样,用(void*)指针接收参数,再用(int*)类型进行强转;另一种就是通过全局变量进行传参:将参数声明为全局变量,然后以下列形式进行传参
DWORD WINAPI ThreadProc(
LPVOID lpParameter
)
{
int* p = (int*)lpParameter;
for (int i = 0; i < 1000; i++)
{
Sleep(1000);
printf("------%d-------\n",*p);
}
return 0;
}
int num1 = 2;
void MyTest()
{
//返回值是线程句柄
HANDLE hThread = CreateThread(
NULL, //安全属性,通常为NULL
0, //参数,用于设定线程可以将多少地址空间用于它自己的堆栈
//每个线程都拥有它自己的堆栈
ThreadProc, //参数,用于指明想要新线程执行的线程函数地址
(void*)&num1, //传入线程函数的参数
//既可以是数字,也可以是个指向某一结构的指针
0, //若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
NULL //线程ID
);
::CloseHandle(hThread);
}
完整代码
#include <stdio.h>
#include <Windows.h>
#include <handleapi.h>
/*
DWORD WINAPI ThreadProc(
LPVOID lpParameter
)
{
int p = (int)lpParameter;
for (int i = 0; i < 1000; i++)
{
Sleep(1000);
printf("------%d-------\n", p);
}
return 0;
}
void MyTest()
{
int num1 = 2;
//返回值是线程句柄
HANDLE hThread = CreateThread(
NULL, //安全属性,通常为NULL
0, //参数,用于设定线程可以将多少地址空间用于它自己的堆栈
//每个线程都拥有它自己的堆栈
ThreadProc, //参数,用于指明想要新线程执行的线程函数地址
(void*)num1, //传入线程函数的参数
//既可以是数字,也可以是个指向某一结构的指针
0, //若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
NULL //线程ID
);
::CloseHandle(hThread);
}
*/
DWORD WINAPI ThreadProc(
LPVOID lpParameter
)
{
int *p = (int*)lpParameter;
for (int i = 0; i < 1000; i++)
{
Sleep(1000);
printf("------%d-------\n", *p);
}
return 0;
}
int num1 = 2;
void MyTest()
{
//返回值是线程句柄
HANDLE hThread = CreateThread(
NULL, //安全属性,通常为NULL
0, //参数,用于设定线程可以将多少地址空间用于它自己的堆栈
//每个线程都拥有它自己的堆栈
ThreadProc, //参数,用于指明想要新线程执行的线程函数地址
(void*)&num1, //传入线程函数的参数
//既可以是数字,也可以是个指向某一结构的指针
0, //若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
NULL //线程ID
);
::CloseHandle(hThread);
}
int main()
{
MyTest();
for (int i = 0; i < 1000; i++)
{
Sleep(1000);
printf("+++++++++++++\n");
}
return 0;
}