00:00
喂。喂喂喂啊,可以感觉卡了似的,好,今天呢,咱们来学一下这个现成的基础啊,那首先呢,咱们包含一些常见的头文件啊,这个STL标准输入输出啊,Windows头文件,还有咱们因为之后要便利线程还得用一下咱们昨天的那个TL32这个头文件啊,那么接下来呢,我们今天来讲一下现成的这么一个概念啊。线程昨天呢,我们讲了这个进程的基本概念啊,进程相对而言呢,它是一个什么呢?它其实是惰性的啊,我们的进程呢,它本身呢,实际上是不执行任意代码的啊,那我们为什么说是进程它是一个程序却不执行任意代码的,这是因为进程本身它相当于一个管理结构啊,它提供了一个内核对象,提供了一个地址空间,但是之后真正运行代码是什么呢?是线程在你在你的进程启动的时候,它会有一个主程啊,随之而启动啊,然后去执行你的这个代码啊,这个是它的一个过程,然后呢,进程呢,有一些资源啊,也会分配给线程来使用,那么我们呢,一般情况下呢,有一个这个默认的主线程在运行,我们今天的话题是什么呢?是除了它的主线程之外,我们如何去使用多个线程啊,那为什么会有这种应用场景呢?比如说我们现在呢,有一个这个外循环啊,我这个循环呢。
01:27
我这个外部循环呢,我就比如说我来打印啊,打随便打印点什么东西啊,不写外部循环了,写份循环吧啊懒得写的次数啊,我们这直接写一个一呃写个100万吧啊这样比较长啊,然后呢,我们直接啊把它的100万给打印出来啊,这个实际上相当于没函数里的啊,这个线程啊,就相当于主线程嘛,然后呢,我们百分号D。好,然后呢,我们这不是有一个这个I嘛,我们对它呢,进行一个打印啊,那比如说我再来一个啊,同样的东西啊,那我比如说我这个写一个made的A啊,然后呢,我这来个的这个B啊,都来一个运行,然后运行完事之后呢,我们到这儿啊system啊,我们让它停在这儿啊,在停之前呢,我们给他打印一个标记啊,告诉他啊,在这个位置上我们结束的一个,呃,执行好,那么我们现在运行来看一下。
02:29
你可以看到我们现在执行的全是A啊,对不对,是A里边的东西啊,然后执行完A之后呢,才会干嘛呢,才会去执行B啊,现在呢,因为数比较多啊,我们可能还会再等几秒才能看到B啊。好,你可以看到啊,已经到B了啊,那这个就是什么呀,这个是因为我们当前啊,只有一个线程来执行啊,所以说啊,在执行它上边这个的时候,底下这个只能等着对不对啊,因为我们是一个顺序结构,不可能说两个一起执行,但是呢,如因为我们这两个东西其实互相之间逻辑是没有什么干扰的啊,我们是完全可以一起执行来节省我们程序的时间的,但是我们现在这种状况很明显是不行的,因为他要等待上一个执循环执行完结束啊,然后才能执行第二个循环,那么这个时候呢,我们就引这个引入了什么呢的一个概念,因为我们现在呢,全都是跑在一个线程里的,所以说他需要等,但是如果说我们开辟两个新的线程啊,然后让他去跑这两个东西,那这个时候我们其实就不用等了啊,就用等了。
03:31
因在并主啊,现在呢,我来这个写一下啊,我们创建线程呢,在Windows下呢,我们使用的线程方式呢,有很多种啊,其中呢,如果我们用Windows windows2的一个原生API呢,就用create three的啊,用这个啊,然后呢,我们下加呢也有three的库啊,Three库好像还有两种版本啊,然后呢,我们都可以用啊,然后我们来看一下它的一个参数啊,我们F12可以看到它这些参数啊,我们也可以直接来这个F1一下,然后看一下它的这个MSDN的文档的一个说明啊,我们通过谷歌浏览器可以直接把它翻译成中文版啊,这样看起来可能更为舒适一些,然后呢,我们看第一个参数,它是一个什么呢?它是一个这个安全啊,安全特性的一个结构指针这个结构啊,确认了返回的句柄是不是可以为此禁程继承啊,如果为no则不能继承这个句柄啊,那这个东西呢,我们可以直接给它填。
04:31
一个闹啊,因为我们用不到它返回的句本是什么东西呢?我们可以看到啊,它返回,因为它创建的是一个线程,我们上节课的这个进程呢,它也返回了一个东西,就是什么呢?就是一个叫做这个呃,进程句柄的东西,那我们现在返回了一个东西是什么呢?就是一个线程句柄啊,他们都是一个handle类型的一个东西啊,我们可以提前啊,把它写上韩总啊,然后h three啊h three的等于create three啊,然后呢,这是第一个参数安全特性啊,我们就直接让它闹掉。
05:02
或者叫安全属性啊,安全属性,然后呢,我们来看它第二个参数啊,第二个参数对战的初始大小以字节为单位啊,系统将四舍五入到最近的页面,如果此参数为零,则新线程使用可执行文件默认大小啊,那这个东西呢,可以看到它是可以为什么呢?可以为零的啊,那这个时候你可以两种选择,一个是填一个零啊,还有什么呢?就是也填个闹,因为闹这个红呢,它本质上而言啊,其实就是一个零啊,我们F12跟进去,你可以看到它DeFine就是一个零啊,它这个是if DeFine的一个plus plus就是西加里啊,Now就是零啊好,然后接下来我们把它啊给它注释一下啊,它是什么?它是堆栈的一个初始大小。虽然说我们现在不用啊,那我们先知道一下它是什么,万一以后我们要用了,我们也可以填,然后接下来第三个呢,这是什么一个啊,它叫什么呢?指向线程执行的应用程序定义函数的指针,该指针表示线程的起始地址啊,那么我们正常情况下刚才也说了啊,当我们进程启动的时候,我们会有一个主线程随之而启动,那么现在这个是什么意思呢?意思就是我们主线程执行的是我们启动代码和我们的这个函数里的一些代码啊,还有什么线程回调的一个里的代码,但是我们这个新启动的线程,它是没有指定你这个代码是什么的,所以说呢,你可以自己来指定啊,那现在呢,你就可以指定这么一个代码是谁,那么这个代码是个什么东西呢?对于我们C加加来说,它其实就是一个函数啊,我们来直接跟进,来跟进F12跟进来之后,你看它这有一个原结构,它这叫start address,其实就是启动地址,但是这个启动地址实际上就是一个数啊,你把函数的地址放在这,然后呢,当。
06:46
启动的时候,它会跳转到什么呢?跳转上函数上去执行,你可以把它理解为另一种意义上呢,直接进行了一次函数调用,但是为什么它不会阻塞呢?是因为它开启了一条新的线程,这条线程呢,是由其他地方来执行的,而不是你主线程执行的,这个呢,也及到C制啊,如果说你是一个单核心的C,其式式行执行,那么我们现在这种呢,是什么呢?是因为你们现在啊,所有的这个电脑基本CP没有单核的啊,基本上都是多核的啊,这个时候呢,就是体现出它这个多线的一种优越性了,但是因为你程序其实很多,但是这时候,所以说呢,这时候你抢也是需要抢占的,而不是说啊,这个每一个这个线程就能独占一个什么呢?独占一个CPU啊,当然了,你在这个李娜的上啊,是有一定机会做到这个的,就是进行定啊,但是咱们这边呢。
07:46
是不不是这样的啊,我们现在呢,可以干嘛呢?看一下它这个函数的一个原型啊,就是这个呃,Three start啊,你可以看到它是一个函数的一个指针啊,我们F跟进去啊,它指针的原型就在这儿啊,然后我们把它复制出来,他DeFine不用复制啊,我们复制后边的部分,我们把它复制出来之后呢,把它这个分号去掉,给它添加一个这个代码块,上面这部分呢,就是函数名,这个是函数标约定,这两部分我们是不需要的啊,我们直接把它空掉,空掉之后呢,比如说我们写一个什么呢?写一个这个嗯的call线程回调啊,比如说这是A线程啊,Call a啊,然后呢,这个是什么?这是它的一个参数,那这个参数从哪传来的呢?是由我们这个后边的一个参数传进来,首先呢,我们在这呢,就可以把它的这个地址传上去,但是呢,他会告诉你啊,这个你填的这个函数地址和它的时参不相同,那怎么办呢?你要跟进去啊,直接把它的这个第三个参数的。
08:46
这个函数人的类型啊,拷贝出来进行一个函数类型的类型强转,这个时候它就合适了啊,那这就是什么,这个就我们可以写一下这是什么线程的线程启动地址啊,实际上什么呢?是函数地址啊,然后也可以说是什么呢?可以说是一种开启一个,也可以说是开启一个新的线程去调用函数啊,这样都是可以的啊,这种说法都是没什么太大问题的啊然后呢,我们啊,下一个参数是什么呢?下一个参数就是我们看到的这个参数啊,我们进来啊,可以看到它是一个什么,是一个P的一个参数啊,我们也可以看一下它的这个描述,这个描述什呢?是给线成的变量的指针啊,也就是说呢,这个实际上是lp word相当于什么呢?相当于一片空,空白的缓冲区,你可以给它填一个结构体进去,可。
09:46
可以填一个数组进去,可以填一个变量的地址进去啊,种种东西,只要是符合他的要求啊,能用一片这个内存空间进行形容的,你都可以给他传进去啊,所以说这个东西呢,没有那么严格的要求啊,如果你想传的时候,你可以直接啊用强转的方式把它转成任意你想要的类型,比如说你这传一个结构体,你在里头啊做一个构体,结构体的一个接收啊,用结构体对它的类型做一个解析啊,也是没有问题的,那么我们如果不用的情况下呢,那这个参数呢,你就可以给他这个什么呢?写一个now啊,那这个参数是数。
10:25
啊,就是这个啊,我们这里传了啊,在我们的函数内部就可以用它来接收啊,就这么一个意思,然后接下来是什么的东西呢?还有还有两个参数啊,你可以看到一个创建的一个flag,一个现成的ID,那这里头对咱们比较有用的呢,实际上是什么呢?是它的这个现成的ID啊,是这个现成的ID,如果你需要的话,你是可以通过什么呢?接收这个ID来进行这个啊控制的啊对它进行制的,但是你可以看到可以啊,如果就不接收啊,这个什么呢?这个呢是给个这个是这个线程生成的一个标志啊,就是线程啊,是在这个创建后立即运行,你就传一个零啊,也就是传个到就可以了,那如果说你传这个啊,创建的这个它是什么呢?以挂起的形式啊创建直到啊,你给它用调用函数给它恢复,它才能继续运行,然后这个是什么呢?这个是这个指定什么,这个呃,初始化大小啊,如果不指定它就按默认的提交啊,那么对于我们而言呢,我们实际上而言要用的就是第零个和第一个啊,就是它的为值为零和为四的。
11:25
时候啊,要么就是什么呢?要么就是啊直接运行,要么就是挂起啊,等会儿再运行啊,这两种形式都是可以的,那我们现在呢,要让它直接运行的情况下呢,我们就可以给他传个零啊,也就是传个now啊标记啊标记啊启动启动标记啊,0X0啊是什么呢?是这个直接运行,0X4是挂起运行啊啊当然024是有一个红的啊,我刚才看到它有一个红的啊,是这个,我们可以直接给它这个用这个红啊来给它创建一个挂起的线程啊,这是没有问题的,然后呢,还有现在最后一个参数嘛,最后一参数就是你要返要不要返回进程ID嘛,不是线程ID嘛,那你可以看到它是一个LP,其实就是什么,就是一个的一个地址,那你现在你如果想要接收啊,你就干嘛呢,你就啊来现在这个位置上啊,直接啊给它定义一个RP three的ID,然后呢,给比如说始化个零。
12:25
个啊呢,你的址啊,那样呢就结束了啊么束后一个就后一个参数就是回值是现成句柄啊,线程句柄呢,基本上就属于什么呢,可以直接去控制我们现成的一个内核对象,所以说呢,你这个东西有没有现成ID对你影响不是很大,通常情况下呢,我在创建线程的时候呢,我喜欢把它后边呢,写一个now啊也比较方便,这个时候你只需要记住什么呢?你需要在第三个参数填它的回调,剩下的都不用管,其实还是比较方便的,然后我们把这个线程A啊给它直接放进去啊,放进去之后呢,我们把它这个啊,May a改成什么呢?Three的call back啊A啊这样呢。
13:25
这里的比较舒服啊,接着呢,我们再给他这个复制一个啊,复制一个干嘛呢?我们给他来个B啊,给他来个B,我们刚才还不是有一个B嘛啊,我们把它这个再写一个B啊淘个B好,接下来呢,我们就可以把这个啊都去掉了,去掉之后呢,我们把给这些东西呢复制复制一份啊复制一份,复制一份之后呢,我们现在呢,就有两个线程了啊,那这个呢,我们要给它把这个启动函数啊,设置成我们的这个B啊,然后这个啊我们要给它分。
14:00
好,那理论上而言呢,我们现成的基本的一个创建啊,就已经完事了啊,那现在呢,我们可以运行一下,看一下它的效果。我看一下啊,它有个错误啊,必须返回一个值啊,因为有一个or啊,那现在呢,我可以直接给他return一下啊,Return一下一会给他return个零啊。好,然后我们运行。现在你可以看到啊,我的这个A和B呢,实际上在交叉的,可以看到啊,他们是在交叉的啊,而且呢,它其实现在属于一种这个并行的一个状态啊。啊,这个这个有点长啊,我就不等了,我给它关掉,然后把数改小一点啊,少一个零的话应该会快一点啊啊比如说我现在呢,再来写一个循环,这个循环呢,是在后边的啊,我写在may函数上,然后这不是may的嘛,啊may的执行啊,然后板块D啊也是一样的啊,也是这么长啊,那这时候呢,我再来运行一下。
15:03
你现在可以看到我的这个屏幕在频闪啊,这是为什么呢?这是因为啊,我的A啊,我的B和我的妹啊,实际上是在一起运行的,我的三个线程是在一起运行的啊,所以说呢,我刚才这个屏幕是在频闪的啊,是在频闪的,然后呢,只有什么呢?这个end啊是在最后执行的,这是为什么呢?因为我这个主线程啊,它是这个end是在我这个循环之后的,所以说呢,只有当我们这个主线程这个循环执行之后,才会执行这个end,所以end必然在最后,但是我这个函数啊,实际上是和什么呢?和我的两个线程啊在同步的跑啊,那这个就是线程的这么一个东西啊,那么我们现在呢,就是有三个线程啊,基础啊有三个线程,如果编译器不给我们起其他线程的情况下啊,我们实际上就是三个线程,什么呢?一个主内函数的一个主线程和什么呢?和两个我的这个子线程啊,他们都在分别跑,并且在同时跑,这种情况下呢,就有利于什么呢?比如说你要同时做一些事情,而他们之间互相又没有干扰的情况下啊,他就可以干嘛,就可以这样做,但是这样做呢,它有一个坏处就是如果说你们。
16:04
同时去访问一个资源,比如一个变量的时候,它可能会造成一些错误,这时候呢,可能会引入一个叫什么呢?叫做线程同步的这么一个概念,线程同步呢,分为这个用户线程同步和这个和这个内核对象这个线程同步啊这个我就今天反正不讲啊,我就不先写了啊,今天咱们讲的是基础啊,就是我先告诉大家一下,我们这里边可能会遇到一个线程同步的一个问题,然后呢,我们现在这种呢,就是什么呢?就是这个分开跑啊分就是一起跑一起跑,那比如说我如果现在啊,我想要干嘛的,我想要这个我的线程一,跑完之后再跑线程二啊,那行不行呢?啊也没问题啊,这个时候呢,你要用什么呢?用一个叫做等待的函数啊,For这个,呃,什么object。
17:00
啊,这个函数,这个函数的作用是什么呢?是等信号啊,我们内核对象它有一个信号的一个概念啊,那我们如果说啊,当前这个线,这个线程执行完了啊,它的状态就会有变化,然后呢,它有变化之后呢,我们这个函数就会往下执行,否则呢,这个函数会帮助你把这个主线程阻塞在这里啊等下去,那么它的第二个参数,第一个参数呢,是什么呢?是你的这个线程要等的这个线程的线程句柄啊,或者说其他的句柄啊,这个其实等什么都行啊,这里呢,只是我们用来等线程,然后第二个呢,是它的时间啊时间,那如果说我们想要一直等着他这呢也提供了一个红啊,叫这个in啊啊这样的啊这个红。啊,这个红呢,本质上就是负一,如果你记不住这个红啊,这个你就直接填个负一啊,也是一样的啊,但是它这写的是0SFF啊,但是本质上而言就是一个负一啊,因为它是一个四节的嘛,我们直接来过来看一下它一个dord嘛,那你如果一个dord你这个计算器啊,因为它是有符号的嘛,我们直接输入啊,一堆F啊,你其实可以看到啊,我不我这底沃的,你看它其实就是负一啊,所以说呢,我们直接填个负一就行啊,不用这么这个费劲,填一个0X8个F啊,我们填个负一效果是一样的,好,那如果用红的,它会相对言可可读性更强一些,然后它的返回值是一个什么东西呢?是一个div,它的返回值实际上是判断了你这个东西有没有等成功啊,它这你可以看到它是有一个return一个值的啊,我们翻译一下。
18:29
它这个值呢,大概有什么几种状态啊,首先比如说啊这个啊,什么通知啊,然后间隔时间已过,或者说超时啊,这个就是超时啊,然后这个是功能失败啊,或者说如果你要确定它怎么失败的,可以用这个盖拉的error啊这个东西啊,那我们现在呢,就不去反呃判断它返回值了,因为什么呢?因为我们是永久等待,在永久等待的情况下呢,它是可以什么呢?它是可以一直等下去的,所以说呢,我们在这边呢啊,只要他的这个线程不返回啊,它这个又就会一直执行,那么当这样的情况下啊,我们可以给他干嘛呢?我们可以再给他等一个啊,就是我们再等一下线程B啊,让他这个分别执行,但这样的话,其实就失去了线程的意义啊,因为它会先执行线程A,再执行线程B,再执行线程C这个主线程啊,那我们来看一下它的效果。
19:16
可以看到我们现在执行的全是线程A,然后线程B,然后主线程啊,这是因为什么呢?这就是因为我们刚才设置的这个主色啊,我们在这等待啊,等待线程返回啊,那你也可以干什么呢?你可以在这样啊直接啊等待它两个线程啊,同时在这等他两个线程,然后干什么呢?然后啊,两个线程都跑完之后再跑主线程啊这样也行。你可以看到啊,现在我AB是交叉的。AB是交叉直行的啊,然后呢,全都跑完之后跑妹啊,之后结束啊,这样也可以啊,也没有问题啊,这个呢,就是我们的线程的基本呃使用和什么呢,和我们如何去等待线程啊,等待线程啊,就比如说你这个线程啊,你一定要等他回来再去执行别的,那你就可以用wait for这个object这个啊,然后再去等它,好,那这个是起和这个恢复线程啊,那首先呢,我们把这个我们现在用完这部分呢,我们可以给它进行一个注释啊,接下来我们这部分啊,暂时用不到啊,也可以给它注释掉。
20:22
我们现在呢,使用的呢,其实呢,跟昨天的代码很像啊,我们可以来进行一个进程,这个现程的一个便利啊,但是它呢,和我们昨天的东西呢,有点不一样啊,首先呢,我们还是返回一个呃,快照的一个句柄啊,具体什么是快照呢?昨天讲过了,今天就不讲了,我们直接啊开始这个进行一个遍历,然后呢,TH32CS,然后SNPID啊好,这样呢,它就是便利线程啊,我们昨天也说过,便利线程的时候,你要提供它的ID啊,那进程ID是什么东西呢?我们可以随随便来一个就行了,比如说我现在呢,启动一下面上这个东西,然后呢,我们找一下的程ID,这静态ID是多少呢?我们看一下啊,是17264啊,那我们回来啊,我们把它的17264填在这,当然了,为了这个整洁,我们也可以这么写啊,我们直接啊,Wordd啊,DW啊,Price ID啊,等于17264啊,是不是我看一下。
21:18
17264啊对没错,然后接下来呢,我们把它的D这个DW process啊,然后我们就直接填上去,填上去之后呢,我们创建快照,创建快照之后,接下来呢,我们就开始什么呢?开始对它呢,进行一个这个便利的操作嘛,因为我们现在已经填好了,填好了之后呢,它现在有会有一个跟我们price entry32一样的这个结构,它叫什么呢?叫做three的ENTRY32啊,然后呢,就是32。我们呢,也需要对它什么呢,对它进行一个初始化啊,这个呢,我们可以来直接fe啊,看一下它的成员啊,我们翻译成中文来看一下,首先呢,我们要填的啊,要先填的就是什么呢?诶他没翻译过来是吗?啊,翻译过来,第一个要先填的就是D这个这个在这个边,我们实际给进行了什么,行了一个这个的填充,因为什么呢,昨天也说过,它的原因是这个结构呢,现在是这么长,以后呢可能会更长,那为了保证它在这个进行扩展之后呢,我们不会有一些错误,所以说呢,我们要提前给它提供一个长度,确保它还是当前的长度,或者说它已经变长了啊这样,然后所以说呢,我们这个东西呢,要提前给它填一下,我们在这儿呢,直接用这个T32点啊,点这个DW DW size啊,直接给它用size off,然后计算一下它当前结构有多大啊,就填充给它就可以了啊好,那么现在呢,我们我就完成了什么呢,结构的一个填充啊,然后呢,我们接下来要开始啊这个获取了,但是呢,我们还要看一下其他的一些东西啊,首先呢,这个东西啊,这个东西呢,我们现在呢,你可以看到啊,它当前已经这个不再使用了啊,并且被一直设置为零啊这个所以就无所谓了,这个呢是什么呢?这个是的一个这个标志符其实就是什么,就是ID,这是什么呢?这是啊。
22:58
程个用的一共三个东西,进程ID,进程ID和线程优先级啊这三个东西啊,那我们现在呢,就可以来进行便利,那它的利呢,也是使用了我们一对这个first和这个next的一个函数啊,啊玩法呢,也跟我们昨天一样啊,就是这个一个波尔值啊,一个is等于啊three的three的32啊,然后first好,然后呢,它的第一个成员呢,就是你快照的一个句柄啊,然后第二个成员呢,是你这个结构的一个指针啊,它会给你的结构进行填充啊,然后他呢,会去寻找第一个啊,找到第一个这个线程,然后呢,返回啊,它是否找成功了,如果找成功了呢,我们通过一个while啊进入什么呢?进入循环啊,来这个获取它的一些信息,比如说我们进行打印。
23:56
我们打印一下什么呢?它的里边的一些东西啊,我们比如说我现在呢,要能打印的东西啊,就是什么,就是他的首先线程ID肯定是可以的,然后接下来呢,我们复制一下。
24:09
线程ID是可以,那我们进程ID肯定也是可以的,那么还有一个可以用的呢,就是优先级,好,那这三个东西啊,那这三个东西呢,我们可以看到它的这个格式化啊,应该都是这个底ord,我看一下啊ordord啊,这个东西不是底ord是个浪啊,但是实际上本质上而言呢,它长度是一样的啊,是四字节,所以现在呢,我们可以直接这么写啊,然后呢,我们现在呢,就可以全部用这个百分号D啊,全部用百分号D。好,现在呢,我们就把它的基本信息啊,当前线程基本信息给他输出了啊,输出之后呢,你可以给他换个行啊,这样呢,看起来可能更舒适一些,但是你可以不换行啊,你可以干嘛呢?你可以这个直接啊,给他再打印一行什么其他的东西。
25:09
比如说你在这儿啊,你可以直接给它打印一个什么横线啊,分割线啊,这些都是可以的啊,然后呢,我们给它去掉啊去掉然后呢,我们现在呢就可以,哎,我操,我刚才好像弄错东西了,我两个一起给它涂掉了。好,那现在呢,我们已经打印完他基本信息之后,我们这只是找到他第一个嘛,所以说呢,现在我们要开始找到第二个了,就是就是什么呢?就是three的32NEXT,然后呢,它的成员呢,跟刚才是一样的,一个呢是这个快照的这个句柄,一个呢是我们这个结构的一个指针啊,然后就是取离纸,然后贴32,好那么他呢,也要接收一下它的返回值,这样呢才能确保啊我们在没有进程的,没有线程的时候,它可以这个结束我们的循环啊好,那么现在呢,我们就可以来给它进行一个便利了啊,我们运行。
26:03
等一下啊,这个啊线程挺多呀,我啊不对啊,我忘记做过滤了啊,这个区别是什么呢?就是我们的线程这个东西啊,还有一个区别,它便利的是所有线程啊,那所以说呢,我们还要干嘛呢,还要判断一下啊,判断一下什么呢?判断一下我们当前的这个进程ID啊,是我们现在出来的线程ID,是不是等于我们自己的啊进程ID,如果是的情况下啊,我们再去打信息,然后呢啊去干嘛呢,去寻找下一个啊,那么我运行。可以看到啊,它这里边有三个啊,三个这个啊,这个先级都是啊,然后呢,ID都是这个啊,然后进ID是这个我们这个的一个便利就成型了,成之后我们还可以什呢,还可以做一些其他事情,比如说我们以那县其实做的呢,可以跟我们什么呢?跟我们的这个进程是类似的操作,那首先我们刚才也明确过了啊,我们一个这个进程它之所运行啊,主要是启动的时候,它启动了一个主线程,然后主线程是可以干嘛的呢?是可以去执行代码的,那现在呢,我们如果说啊,把它所有的线程都干掉的情况下,那实际上那么这个进程也就扑街了啊,也就不了,那么这个时候呢,我们就这个线程也就没了啊,那我们就我们进程也就没了,那所以说呢,我们可以干嘛呢?我们可以干掉啊,干掉干掉所有这个程啊,使程出啊,那这个东是什么东,现在就是个数。
27:36
它有两个参数,第一个呢是现成聚柄,第二个呢是退出代码,那这个现成的一个聚柄呢,我们是打哪来的呢?我们现在不是有这个现成ID嘛,那么这个时候我们就可以调用一个叫open thad的这么一个函数啊来进行获取,首先呢,它的第一个参数还是你要打开之后它的一个权限啊,打开线程嘛,我们打开什么权限啊,我们可以这个啊,然后直接一个所有权限,然后返回的句柄是不是继承啊,我们直接一个啊不继,然后第三个呢,就是你要打开的这个线程的线程ID是什么?那我在这贴32里便异理出ID了,我直接把这个ID填进去,填进去之后呢,我们open three它也是返回一个handle,也会是返回一个线程句柄,那所以说呢,我们在这个位置上啊,我们可以直接接收到这个线程句柄,那我们把这个线程句柄传给这个结束的函数,然后给它传一个这个,比如说传一个负一啊,异常退出啊,这样就行了,那么我们现在呢,就可以来运行尝试一下啊,我们把这个拉到一边上啊,然后把这个程序放在这,放到这之后我们现运。
28:38
可以看到啊,它没了啊,它没了啊,而且我们这边只显示出一个是什么意思呢?因为我们把它这个主线程干掉之后,它直接就挂了啊,所以说呢,其他线程没来得及便利它就摁了啊就这么一个意思,好,那这个是什么呀,这个呢,实际上就是结束线程,那我们还有一些什么呢?还可以让线程暂停啊,我们是可以挂起线程的,我们的Windows是支持挂起的啊,那么这个是怎么做的呢?我们比如说啊,我现在呢,还是这个呃,进程啊,我找一下它18080啊,我替换一下18080,好,那么还是同样的啊,我就不用什么呢,不用给它使用这个函数了啊,我们现在呢,可以使用一个挂起。
29:19
呃,SUSU啊好,它的参数呢,我们可以看一下啊,你看它就一个线程句柄啊,然后我们可以看一下它的函数描述,F1跟下MMSDN里边啊。它是什么呀?你看啊,就是挂起啊,挂起指定的线程啊,然后它还有一个函数叫什么呢?64位的应用程序,可以用这个64版本啊,然后这个函数啊,还有一个函数啊,刚只是前面加了一个O64,然后来挂起这个64的一个进程,这个实际上它这个说法有点问题啊,因为64进程不是六四的一个应用程序啊,也可能是翻译的有问题啊好,然后呢,我们现在呢,就可以干嘛呢,我们就可以直接给它传进去啊,传进去之后我们现在啊来运行一下啊,现在你看它是可以自己自这个各种拖动的啊,那么我们运行。
30:10
运行完事之后啊,我们来再拖它啊,是拖不动了的啊,你看点也没有反应了,看着没啊,关都关不掉啊,这是为什么呢?因为它已经线程被挂起了,那线程被挂起之后,这个程序相当于死这儿了啊,相当于死这儿了,但是呢,你还可可以干嘛呢?还可以给它恢复回来啊,使用另一个函数,你就可以把它挂起状态的这个线程重新给它运行起来。嗯,Re sum three啊,它的参数一样啊,也是一个线程句柄,我们直接传进去啊,传进去之后呢,现在呢,我们直接来运行。回撤,诶,你看他能动了啊,该点什么他也有反应了,对不对啊,这个就是什么,就是线程已经被恢复了啊,那恢复完事之后呢,我们顺便啊再运行一次结束啊,送他去送他走啊就完事了,送他走哎,他就没了啊。
31:04
好,那以上呢,就是咱们今天线程相关的啊,基础操作啊,就已经全部讲完了啊,常用操作基本就这些啊,当然了线程同步没有讲啊,这个基本上就是函数的使用上的常用操作啊。然后大家还有什么问题没有。
我来说两句