跟着 rkvir 老师学学今天的知识,今天的课程是 《Windows系统编程》——线程基础与相关结构

课堂笔记

引入

线程(Thread)就是程序执行的基本单元,一般我们写的程序只有一个线程。

当两个事件之间相互没有关联,不会影响的情况下,我们可以采取多线程的方式去节省其空间。就好比小学三年级的课程,如何加速一个泡茶的过程,最主要就是烧水的时候我们大可不必傻傻的等水烧开,我们可以利用这个时间做别的事。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#single thread
#include<stdio.h>
int main()
{
for (size_t i = 0; i < 20000; i++)
{
printf("A execute for %d times\n", i);
}
for (size_t i = 0; i < 20000; i++)
{
printf("B execute for %d times\n", i);
}
getchar();
}

在这里,我们的两个循环很显然上面执行完了才会执行下面的循环,如果我不要求输出顺序,我的要求只是让你输出,那么我就可以 A B 一起输出。

CreateThread函数

在 Windows 当中,我们使用 CreateThread 函数来创建一个线程,并调用回调函数。

第一个参数是安全属性,第二个参数是堆栈大小,第三个参数是回调函数,第四个参数是线程函数的参数,第五个参数是启动标记,第六个参数会返回线程的ID。

返回值为线程句柄。

WaitForSingleObject函数

可以用于指定程序等待线程返回,第一个参数指定线程句柄,第二个参数指定等待的最多时间,可以用 -1 表示无条件等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
#include<TlHelp32.h>
#include<Windows.h>
void CallBackA() {
for (size_t i = 0; i < 2000; i++)
{
printf("Hello World\n");
}
}
int main()
{

HANDLE hThread=CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)CallBackA,NULL,NULL,NULL);
WaitForSingleObject(hThread,-1);
printf("I fade away\n");
}

如果我们不加 WaitForSingleObject 去等待线程调用结束,我们会发现 I fade away 不一定会在最后输出,而加了则一定会在最后输出,这个函数可以在某些语句必须在某些语句之后执行这样的约束条件中使用。

遍历线程

用之前的函数去创建线程快照,然后用对应的 entry 去遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
#include<TlHelp32.h>
#include<Windows.h>
int main()
{
DWORD pid = 0;
printf("pid:");
scanf_s("%d", &pid);
HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,pid);
tagTHREADENTRY32 te32={sizeof(te32)};
int ret=Thread32First(hsnap,&te32);
while (ret)
{
if (pid == te32.th32OwnerProcessID) {
printf("tid:%d\n", te32.th32ThreadID);
}
ret=Thread32Next(hsnap, &te32);
}
}