下面呢我们来介绍一下我们这节课当中最重要的一个知识点,就是信号信号量常用的 a p i 函数的一个使用,这个呢在我们编写程序的时候啊,对这些函数啊,一定要啊了如指掌啊,知道这个函数的一个用法。首先我们看一下创建信号量的函数, 创建信号量里面呢,我们主要介绍二字信号量和技术型信号量。首先我们来看一下创建二字信号量这个函数,那么这个函数呢,是用于创建一个二字信号量的,并且呢返回一个句柄 啊,那么其实啊二字信号量和互字信号量呢,都共同使用了一个类型啊,这样的一个句柄, s e m a p h o r e h a n d l e 杠 t, 这是我们的一个消息啊,对列或者说我们的一个信号量和互质量,他共同使用的一个类型的一个句柄,那这个句柄的原型呢,其实是一个 word 的啊类型的一个指针,使用这个函数创建的二次信号量呢,都是空的。 那么在使用我们这个呃销量获取的时候啊,获取之前啊,必须先要调用这个函数来释放,释放才可以进行获取, 如果是使用老式的函数啊,也就是这个函数创建二次信号量的时候呢,他会为一,在使用之前呢可以不用释放。 那要想使用这个函数呢,必须在我们的一个配置文件当中把对应的一个红定义呢,设置 唯一,也就是开启动态内存分配。那对于我们这个呃 few ids 创建的工程模板来说,我们已经把它给设置为一了啊,设置为一了,下面我们就来看一下我们的这个创建二次信号量的具体的一个函数 啊,这个哈,这是我们的一个创建二指信号量的一个呃,具体的一个函数的一个原型啊,所以呢,我们在使用它的时候,首先把这个红啊给设置为一啊,设置为一, 然后呢设置为一之后,它里面的这个语句呢才能执行,它其实就是一个红,红里面呢调用了这个函数,调用这个函数, 从这个函数的原型呢,我们就可以知道,二指信号量的创建呢,实际上使用的函数呢就是这个啊, 是不是很如意呢?这个就是消息对列创建使用的函数,但是参数啊是不一样的啊,根据这个函数的原型,我们来讲解一下它的一个参数的作用。首先我们来看一下第一个,第一个参数呢是表示 这个消息创建的队列长度为一,那么其实呢是用作呃,消息用作我们的信号量,就是表示信号量的最大的可用个数。从前面的知识点我们知道二指信号量,那么要么就是空,要么就是满,所以呢,它长度就是一 啊,长度就是一。第二个这个红啊,这个红其实就是一个用来表示啊,这个红的值呢,其实就是零啊,其实 就是零,表示我们创建的消息空间呢,它的大小呢为零,因为这个所谓的消息对列其实并不是用于存储消息的,而是被用于二值信号量, 因此呢,我们根本不需要关注这个消息里面的内容是什么,所以呢,我们把它的一个长度设置为零就可以了。 然后第三个成员呢,表示的是创建消息对列的时候的一个类型啊,在我们的这个对应的 q u e u e 点 h, 这个对列的头文件当中呢,有定义,那我们看一下,他这里传递的是一个二值信号量的一个头文件啊,一个一个红啊,一个红,那表示是我们这 这个函数呢,是创建一个二指信号量的一个函数啊,那么具体你要设置的是哪一个值呢?可以在这个头文件当中啊查找得到。比如我们现在这里设置的是二指信号量, 也就是这个啊,也就是这个,那这里呢有一个基础的啊,户次信号量,技术型信号量啊,还有低规啊,低规啊等等。 那可能有很多人会问啊,我们创建一个没有消息存储空间的对列, 那么这个信号量用什么表示呢?其实啊,二指信号量的释放和获取都是通过操作对列结构体当中的一个成员来实现的,那这个成员呢,就是我们前面介绍的啊,这个值,这个值 啊,它表示信号量中可当前可用的信号量的个数。在这个信号量创建之前呐,这个变量值呢是为零的, 这说明当前信号量处于无效的状态,此时信号量是无法被获取到的。在获取信号量之前,我们应该先释放一个信号量信,释放一个信号量,他才能加一,这样我们才后续的任务呢,才能进行获取。 这是我们的一个二值信号量创建的一个函数,大家知道一下,我们直接调用这个函数的时候,就可以实现我们的一个二值信号量的一个创建, 然后呢调用这个函数的时候,他会返回一个呃信号量的一个聚饼啊,信号量的一个聚饼。 后续我们要对这个信号量进行操作的时候,我们就直接对这个据柄啊进行操作获取和释放啊,这是我们的二次信号量的一个呃创建的一个函数, 下面呢,我们再来看一下我们的一个技术信号量的一个创建函数,那技术型信号量创建呢?其实跟我们的一个二字信号量创建其实差不多啊,差不多。那我们来看一下我们的技术型信号量,这是他的一个函数,这是创建技术型信号量的一个函数的原型 啊,用于创建一个技术信号量,那么这个函数里面有两个参数,第一个参数呢,是用于技术信号量的一个最大值,当达到这个值的时候,信号量就不能再被释放了啊,不能再被释放, 也就相当于啊,一个最大值啊,最大值,比如说我们的一百啊,你不可能是一百零一啊。然后呢,这个第二个值呢,是用于创建技术信号量的一个初始值,初始值啊,比如说零啊,零。 如果说我们创建啊技术型信号量成功的话,那么返回一个技术型信号量的一个句柄啊,这个句柄, 然后呢用于访问创建技术型信号量啊,因为我们后续要访问这个技术型信号量的话,都会通过这个句柄来实现啊,访问。如果说我们创建失败,那么返回是 now 啊, now 技术型销量跟二指型销量的创建过程呢,都差不多啊,也是间接的调用了 这么一个函数啊,跟我们的二次信号量呢一样,调用这个函数只是它的一个类型啊,不同而已, 这是我们的一个创建技术型信号量啊,创建技术进行技术型的一个信号量,下面呢我们再来看一下我们的一个删除信号量,删除的一个函数,那么我们要对这个信号量呢进行一个删除的话,那我们可以调用这个函数来删除 这个信号量,删除函数可以用于删除一个二字信号量信号啊,技术型信号量,户次量以及地规户次量,通通都会调用这个函数来删除它啊, 如果说有任务主色在这个信号量上的时候呢,我们不要去删除这个信号量啊,注意一点,这一点啊, 就是说我们的任务啊,在等待某个信号量的时候啊,那么你不要在其他任务不要去调用这个删除信号量的这个函数了, 那你删除的话,那这个任务就没办法得到这个信号量了,对不对啊?所以这是这个删除啊,删除的一个信号量的一个函数,那么这个函数的原型就是这个, 然后呢里面呢是要指定你的信号量的一个句柄啊,你要删除哪一个,就通过你创建信号量的时候得到的一个句柄传递进来就可以了。删除信号量过程呢,其实就是删除消息对列啊,通过调用这个消息对列的删除函数, 这是我们信号量删除函数啊,然后我们再来看一下信号量的一个释放函数,那么有啊,他的一个创建, 那么我们也会有释放啊,有释放啊,跟我们的消息对列操作是一样的,销量的释放呢,可以在任务中断中使用,所以呢,我们需要不一样的 a b i 函数, 对于我们普通的任务函数当中,我们可以通过这个函数来实现我们的信号量的释放。对于我们使用中断函数里面要释放某个信号量的时候,我们就要带中断保护的这个函数 from isr 啊,这是这两个函数的一个区别。 在前面的讲解当中,我们知道当我们信号量有效的时候啊,我们的任务呢,才能获取到信号量。那么是什么函数使得信号量变得有效呢?其实有两种方式啊,一种是在创建的时候,对他进行初始化, 将它可用的信号量个数呢,设置为一个初始值啊,在二十信号量当中啊,初始值的范围呢,就是零和一啊, 假如初始值为一的话,表示一个可用的信号量,那被申请一次就变得为零了,也就是不可用了,那需要我们释放信号量才变变为一,又变成可用。 那么这里的释放就是调用我们的这个释放的这个函数,每调用一次这个函数呢,就释放一个信号量,但是有一个问题哈,能不能一直释放呢? 很显然这是不能的,无论你的信号量的是二指信号量还是技术信号量, 都要注意可用信号量的一个范围,当用作二指信号量的时候,必须确保它的可用范围是零 一二零一。而用作技术型信号量的话,那么他的一个可用范围就是在你用户创建这个信号量的时候,他会指定一个最大的一个技术的一个值,你的最大可用信号不允许超过这个值, 这样呢,我们就不能一直调用这个释放信号量函数来释放这个信号量了,其实一直调用也没有办法 释放成功啊,这个在 fil rts 的底层呢,它就已经通过这个值来判断了你即使你等于这个值,你再释放的时候,它也不会释放成功的啊。 所以我们在写代码的时候,虽然说它的底层已经帮我们判判别了,但是我们尽量不要这样去做啊,我们要让我们的代码呢更严谨啊,更严谨, 这是我们的一个信号量释放它的一个作用。现在呢我们来看一下普通任务当中调用这个信号量的一个释放函数,它这个圆形啊,就是下面这个也是通过一个红啊,实际上就是调用这个函数对列的一个发送的一个消息的一个函数啊。 那我们要在使用这个信号量释放的时候呢,必须要确保他是信号量已经是创建的,那么那我们要对信号量,哪些信号量的二次信号量,技术型信号量互质互质量的 释放呢?通通都可以对这个函数的一个调用,但是要注意一下,如果说你使用的是这个函数创建的一个什么地规复制信号量的话,那你不能调用这个函数来释放它啊, 而且这个函数呢,是不能放在中段里面进行操作的,在中段里面的话,他会有一个专门用于中段保护的一个释放函数,就是下面这一个啊,下面这个, 那我们在释放销量的时候呢,在控制快当中呢这个成员, 这个成员他会进行加一,这是我们的一个释放啊,我们的信号量的一个释放的一个函数, 释放了一个函数,那我们再来看一下,我们在这个中断函数当中要释放一个信号量的话,那我们就要调用这个函数来啊,实现啊,因为这个函数是带中断保护的,看到有 from i s r 就可以知道它是应用于 中断符函数里面进行释放信号量的啊,那么释放的信号量跟这个是一样,可以释放为二字信号量和技术型信号量。那对于啊使用啊,这个创建的这个地规互刺的这个信号量来说,不能通过这个函数来释放, 那么这个中断带中断保护的这个释放销量的这个函数啊,和我们普通的这个函数是有些不同的,它不能释放 户质量啊,这是因为户质量呢,不可以在中断中使用啊,户质量的优先级继承机制啊,只能在任务中使用, 而在中断中呢就毫无意义。带中断保护的信号量释放呢,其实也是一个红啊,就是下面的这个啊,下面这个它里面呢也是调通过这个函数来调用啊,消息对列的一个呃,获取函数啊,释放释放的一个函数, 那这个函数里面呢,有两个参数,第一个是我们的一个销量的一个句柄,注意,在我们的这个 释放带中断保护的这个释放函数里面呢,不能用于释放护质量,刚才我们也说了啊,护质量他是不能在这个中断里面进行使用的。然后呢,第二个呢, 是它的一个可选的一个参数,那可以设置为 now 啊,可以设置为 now, 这是我们的一个释放信号量的一个函数啊, 我们再来啊,再来重复一遍啊,我们这个释放信号信号量的函数,这个呢是用于普通的一个任务,这个呢是用于我们的一个中断的一个符号函数里面对信号量的一个释放, 这个函数呢适用于二指信号量,技术型信号量和护士型信号量,通通都可以释放,然后呢这个函数呢用于二指信号量啊,以及技术型信号量, 那么对于呼市信号量呢,它不适用,所以呢它们之间的区别大家一定要注意。 接下来我们再来看一下销量的一个获取, 那么有释放啊,必然有获取,那么这是我们的一个普通任务的一个信号量获取的一个函数,这是它的一个函数的一个原型,它其实上就是调用了这个消息对列的一个接收的一个函数。那么我们来看一下信号量获取的函数当中呢, 它里面有两个参数,第一个呢是消息的信号量的一个句柄,第二个呢是它这个信号量的一个主摄时间,因为我们要获取这个信号量 啊,当我们资源里面有这个信号量的时候,那我们当然可以直接获取,如果说没有的时候呢,那你通过这个组成时间可以设置为 直接走还是等待,还是说一直等待,就通过这个时间来指定。那么调用了这个信号量获取函数的时候呢,那么 控制块里面的那个变量啊,里面的一个值,这个值呢,它会减一啊,释放的话它会加一啊,所以这个一定要注意啊,那获取之后呢,它会有一个 返回值啊,通过调用这个函数的时候,它会有一个返回值,如果获取成功,返回 cure, 如果说获取失败,那么就是这个, 那我们要获取信号量呢,可以通过,可以通过这个函数获取二值信号量, 技术型信号量以及互次量,这个函数只适用于普通的任务函数地规互次量呢,不能使用这个函数来获取,它有 专门的自己的一个函数来获取啊,来获取,注意这个只是普通的任务函数里面使用,对于在中段符函数里面要获取销量的话,不能使用这个函数啊,那么他会有一个专门的一个函数, 带中断保护功能的啊,信号量获取的一个函数,那么在中段服务函数里面要获取信号量的话,他只能获取二次信号量和技术型信号量,跟啊信号量的一个释放是一样的, 那互字销量呢?他是不能直接在这里中断里面获取的啊,这个函数的一个圆形呢,是这个,是这个啊,那么这个函数返回值啊, 如果获取成功,它就 char, 没有的话就是这个这个成员啊,这个返回值, 那么这个函数的参数呢?有两个,第一个用于指定我们的信号量的一个句柄,第二个呢,你可以设置为空啊,设置为空 这个函数呢,适用于我们的一个中段符号函数里面啊,如果说你的是要在普通任务函数里面,那你就调用这个函数来释放啊,获取我们的信号量,如果要在中段里面获取信号量的话,那你就调用这个啊,调用这个, 这是我们销量获取的一个函数的一个介绍啊。同样的这两个函数的区别呢?第一个,这个适用于普通任务函数,在中段里面不适用。 第二个,这个适用于中断符函数啊,它带有中断保护功能。然后呢,这个销量会 获取呢?它只能获取二字信号量、技术型信号量和互字信号量。而带中断保护功能呢,它只能获取二字信号量、技术型信号量,互字信号量它不能获取,这是这两个函数的一个区别。
粉丝1205获赞5224

各位粉丝朋友,我们今天在我们的什么一个微编的窗子上了吗?来玩一个什么?呃,一个数字,始终的运气问题, 嗯,有粉丝提到一个问题,他说,嗯,他做这个窗体上哈,如果说加入时间或者说倒计时的时候,他不会起作任何作用,这里面就出了一个问题啊,所以说这里边我今天做了一个小作品,给大家做一个分享。 那么首先呢,我们来看一下啊,嗯,如何来实现这些问题? 嗯,在我们的桌面上呢,我们首先还是,呃,继续怎么样呢?点开我们的什么呢?我们的 excel 啊,首先我们看一下, 首先那个始终大家都知道,呃,他运行的时候哈,是如果在窗底上,如果你的显示方式不对的话,会出现一个比较麻烦的一件事情, 如果不对的话,那么就怎么样呢?那么就压根就是不起作用啊,那个施工就说一个时间,那现在我们来打开,我们来看一下, 打开我们的云盘里边了哈, 啊,他正在从铭盘上下载 啊,在这里边我们点击什么呢?先是看一个效果吗?呃,这里边哈,我们有一个按钮,我们点击个按钮 要用出来,看能不能出现,你要这个时钟,现在我做这个就文文妥妥的话,在这个穿上显示,所以那个粉丝可能他忽略一些细节,我们今天帮他做一个强调这个知识点, 如果是现在呢?你看我点击其他的时候,点击这个窗底外的时候,我如果用鼠标,比如说像这里边啊, 呃,有一个关闭按钮,如果点击其他,你看啊,他就会关闭了哈,你看我在这里边看一下后台如何实现的,我们来看一下。 首先我们建立一个窗体用户,窗体在这里比较简单哈,这个窗体呢,我们待会初始帮他调整把模式,呃,在这里边我们都没有设置,然后呢 我们进入我们的什么呢?这里边数,这,这边是数据,数据啊,唱这个标签很简单, 我们来看一下我们窗体里边的现在代码哈,首先是在他初始化的时候,我们就做相应的操作, 在这里边我们首先可以看到他那边还有颜色,还有上面的对象的一些参数,以及这个窗体本身的感宽高 啊,还有这个窗体卸载的时候,他有什么东西卸载,就是 uniform 下面这个东西啊。然后我们再看模块里边,模块里边我们首先是调用这个外物的 api 函数 啊,这个 apa 函数呢?如果说你现在如果说是哈,如果是 office 是六十四位版呢?应该在我们的 degree 旁边,我萨火前面叫 ptrcf 这个关键字 啊,我们现在把加上哈,因为这是为了照顾我们的六十四位的。什么呢?一个 offer 是稳当的时候,我们才这样做的, p t r c f, 回首空格键好, 然后他就以安全的方式去教育我们的什么呢?我们的内核都什么呢?是利用函数,这是睡眠函数。 然后呢在这里边我们就首先是调用这个窗体,零表示什么呢?我们这个窗体运行的时候,我们可以干其他事情,就这个意思啊,就是说我们如果 你不这样做的话,那么这窗里那你其他事情干不成,所以我们采取零的方式,有一个零的操作,我们下面才可以通过模块这个窗体外部的方式跟他动态的,像这个窗体传输,我们的传输叫通讯传输。 好,我们来再一次运行一下,看一下,看他是没有问题啊,所以那个粉丝可能多半是就是那个调用窗体的问题,还有那个对方时间显示 他是有问题的啊,不能够进,像我这样做了之后他就可以非常方便一种。好了,我们今天就跟大家分享这个地方,希望对这位粉丝和广大同志有同样的问题啊,可以提供一个帮助。好了,谢谢大家的观赏。

哈喽,大家好,我是小李老师,今天是咱们的第六课,我们来讲一下 api 函数的 a 和 w 版本,在调用 api 函数的时候呢,要注意啊,比如说我们去搜的时候啊,我们去搜索东西啊, 我们搜的是 message box, 对不对?但是呢,我们最终呢写这个函数的时候,或者说最终调用这个函数的时候,看到没有,我们掉了一个什么东西呢?掉了一个 message box, a 为什么掉了一个这个加了一个 a 的一个东西呢?啊?他的一个由来呢?是怎么回事?其实在之前我们就讲到过,他跟这个字符的这个编码是有关系的,我们再来看一下这个书里边,这个教材里边怎么说的, 他说在这个 win 三二环境中呢,和字符串相关的 a, p, i 呢,共有两类啊,有两种,分别对应两个字符集,就说,呃,这个字符串啊,这个字符啊,它是有差异的, 是分成两种,那一种呢?是处理 n, n, s, i 自负器的,另一类呢是处理 unniko 的自负器的,就这两类啊,而且呢呃,全部都是跟这个字符字符或者说字符串相关的,那我们比较熟悉呢,这个 n, n, s, i 呢?呃, 这个是比较常见的啊,你如果说能看懂就看,看不懂的就拉倒了,就说他是 c 员里边的,如果说大家想学 c 员,可以在这个哔哩哔哩啊,咱们这个工坊里边呢,有那个 c 员的课程啊,现在就是九十八块钱啊,粉丝价九十八, ok。 呃,比较熟悉的是这个啊,这个有什么特点呢?之前我们就说过,每一个 nsi 字符呢,它是占一个字节宽一个字符,比如说 abcd 这种呢,一个 a 就占一个字节,一个 b 就占一个字节。这个对于欧洲语言体系啊,就是说,呃用英语来交流啊,或者说用拉丁系的这个字母来交流的话, 这个 nss 父亲呢,已经非常足够了,对吧?但是呢对于咱们这个中国、韩国、日日本啊,或者说其他的一些,呃国家,他的这个语言体系啊,可能有成千上万个不同的字符,对不对?英语他有几个? 二十六个对吧?二十六个,这个 a、 b、 c、 d、 e、 f、 g, 对吧?但是呢这个汉字呢,对吧?汉字就特别多啊,而且还有什么繁体字啊,等等等等,对不对?所以说呢,这个 n、 s、 i 呢,它就不够了啊,它不够了啊,那怎么办呢? 呃,后来呢,他就发明了这个 unico 的字符集,那发明了这样一个字符集,那这样一个字符集有什么好处嘞?就是每个 unicord 字符占两个字节的宽度,这样的话呢,就比较统一,比如说一个字啊,他比较复杂,或者说一个字他比较简单,然后呢全部统一成两个字节宽度, 这样的话呢,在编写程序的时候呢,呃就不会出现那么多的一个问题啊,这样一来呢,就可以同时定义啊,六五五、三六个不同的字符, 比如说呢,他为了这个语言体系啊,为了能够更加的兼容,所以说他发明了这样一个东西。好,那对于 apr 函数来说,呃,并不是所有的,并不是所有的函数啊,都都是需要我们传入字符串的,懂我意思吧? 你看到没有,你像这个 exit process 这个函数的这个意义呢?就是退出程序,或者说退出进程, 那退出进程的话他不需要传入啊,因为,呃他说了某句话而退出了还是怎么怎么着呢?他不需要那些乱七八糟的一个参数,他不需要传入字幕串的一个参数,懂我意思吧?所以说他就不会出现 a 和 w 版本, 但凡是有 a 和 w 版本区分的啊。但凡是有这两个区分的是怎么回事呢?但凡是有这两个区分呢?是因为我们需要传资物串,懂意思吧?我们是需要我们传资物串啊,所以说,呃 嗯,如果说这个函数他没有字符串的话,如果说没有字符串他就不会有两个版本啊。 ok, 然后呢再往下简单的这个了解一下啊,并不是每个 win 三二系统都支持 w 系列的 api, 在以前的时候比如说 windows 九八啊, windows 九 x, 那这个系列中呢,对 unicord 是不支持的,只有在只有到了这个温度的 nt 系列才对这个 unicord 的完全支持 啊。所以说呢为了编写在几个平台中通用的程序啊。呃其实呢我们是一般呢。呃是用这个 nsi 比较多啊,一般我们在国内啊写程序啊都是 nsi 这个版本比较多一些, 懂我意思吧? ok 简单了解一下啊。呃总结一下第一点呢就是说 a p i 函数啊,为什么会有 a 和 w 版本啊?如果说是有这两个版本的话,他们一定是会传入字符串的,比如说 message box, 它需要提 式的信息,他需要标题,那这些呢都是字符串,懂意思吧?如果说他没有这个他不需要传入字符串信息的话,他就没有 a 和 w 版本, ok, 这这个哈,好,然后呢?嗯,这个留着下节课再说吧。分开啊,分开讲。



hello, 亲爱的小朋友们,大朋友们,我是狒狒,这一节课呢,我们录一个答疑课,呃,因为有一些粉丝,他说这个,能不能去讲一讲怎么去使用 windows api? 那么一般有这样的疑问的啊, 大概率都是新手,就是新手喜欢去折腾这种东西。嗯,有开发经验的这些程序员,他通常不会去折腾这个, 他可能就是说,如果你对 windows api 需求比较大的,他可能不会去使用 c 叉,把它改用 c 加加等等。所以你要使用 windows api, 那么你就必须对系统底层的一些 windows 给你提供的一些程序接口,你要比较熟悉。比如说, 呃,开一个, 把字调大一点好。 windows a p i, 我们要知道 a p i 是什么东西? a p i 当中的 a 呢,指的是 application, 就 a p p 就是应用程序的意思, p 呢,叫做 public, 就公共的。如果我没记错啊, i 叫做 interface 接口。所以 windows api 指的是什么东西啊?指的是 windows 应用程序,公共接口指的是这个。那么你看到的所有的窗体它是 是怎么画出来的?它都是通过 windows 底层一些 api 画出来的。那这些 api 在哪里呢?我们来看一眼这个。刚才我在网上截了个图,就是说 windows api 就是 windows 应用程序接口,是针对微软的 windows 操作系统家族的系统编程接口。 那同样啊,当时我们说跨平台的时候,为什么说微风不能跨平台呢?是因为你看到这些窗口是使用 windows 底层的这些 api 画出来的,对吧? 你把它换到 linux 或者是 max 下面的时候,它没有这个 a p i, 所以就画不出来,就这么简单啊,就这么简单,画不出来,那么这些 a p i 这些东西被放在哪里了?它都放在 d l l 文件里,比如说 corro 三十二点 d l l, 你平时不大容易见到 到,但是你如果对操作系统底层嗯,有过了解的话,你对这个东西肯定不陌生,对吧?这个内核包括之前的那个系统进程里面 啊,我们不说 win 十一啊,就说比如说 win 七啊、 xp 啊、 win 八啊等等,这些系统,它的系统进程里面可能都有这个东西, 你不信可以回头去看一下,对吧?那么 a p r 函数呢?分为好多类,那这个只是其中一部分,就是基础服务啦,图形设备接口啦,然后图形化用户界面啦, 还有什么通用对话框,呃,链接库了等等。这些东西很多啊,它每个里面有好多好多函数,它就相当于这 d l m, 就相当于我们 c 下里面一个内裤, 一个内裤里面有好多个类,每个类里面有若干个方法,对吧?所以他是非常庞大的,你如果想去了解的话,可以去网上去搜一搜 api 查询,或者是去 呃找专门的书籍去看一看。这些 a p i 它分别是叫什么名字,有什么作用?这个需要自己去熟悉,自己去查。没有办法说我一节答一课全部给你讲完啊,这需要自己去查。那么 有一些东西啊,你不用 a p i, 好像看似无法完成,比如说 我想把这个窗口的标题改掉,有人说这改掉简单啊,你把这个保存一下,给他改个文件名,再打开就是他的标题了,对吧?啊?我现在这边有一个程序,我有一个播放器, 把它的这个改掉,把它的标题就是这个福霸二零,呃,二零零零 v 一点六点一二,把这个改掉,或者是我把这个回收站上面的这个回收站改成垃圾箱, 那这个思路是什么呢?它既然是 windows api 画出来的,我们就可以去获取这个窗口的锯柄,那锯柄是什么东西呢? 句柄我们可以把它理解成窗口或者空间的身份标识,就跟人一样有个身份证,对吧?一个身份证号对应一个人,他还是一样的。当这个窗口开启的时候啊,被划 出来之后,他也有一个身份标识。那我们今天呢,就拿这个啊,获取窗口句柄,然后修改窗口标题来做个例子,看看怎么去用啊?首先你要知道他是在哪一个 da。 我要想啊, 就是首先你要知道你需要的功能在哪个 d l l 下叫什么名字。 有人说我,那我这个我哪知道啊?因为你是新手嘛,你当然不知道,对吧?如果你是对这个系统提成打交道比较多的,这个毫无疑问你都会知道,那你不知道怎么办?去查呀,是吧?呃,然后呢,如果你是在 c 下不下 去使用 a p i 的话,你要进行 d l l 引入,然后呢?引入了之后呢?声明 a p i 函数的签名,就是说这个 a p i 函数其实它已经在 d l l 中给你写好了,那么你要用呢?你得给它把签名声明出来,对吧?然后再调用它就可以了。 过程大概是这个过程,那么写起来他这个跟我们平时写的有点像,但是又有点不一样,我们来看一下吧, 我们创建一个文化民用程序啊,还是当年的 framework 吧, 这么 a p i。 好,这边有个窗口,我们给他稍微改一下啊,让他居中,然后呢?不需要在的话,这小花按钮,嗯,窗口不能调整大小, 然后标题改一下,叫 window cpi 简单视力。 好啊,好,这样啊,我们在里面放,放两个 label, 一个两个,然后放两个文本框,然后放两个按钮。 我们要做的就是刚才我说过了,去找一个窗体,就找到一个窗口的句柄,然后呢,把它的标题给它修改掉, ok, 嗯,还有一个是吧? 好,我们来给它改一下,这个我们就只改文字了。 level 就只改文字啊,窗口标题,你要找一个窗口呢?你得知道 他的标题是什么,对吧?好,呃,按照窗口表体去找窗口,找到了之后获取他的句柄,就是窗口句柄,然后呢,这个是新标题。 好,这一个我们把名字改一改,因为要调用它 text title 窗口曲柄, text h w n d 这个 text new title 就是新标题,然后这个按钮呢? button get h w n d, 这个呢? button set title。 好,这个叫做获取窗口,获取句柄,这个呢?设置标题, 那么这个窗口具体是获取下来的,所以我们不用去改它,把它改成 read only。 好,这样一个 g m 就写完了,对吧?就做完了,然后我们看看怎么去获取距离啊?首先我们刚才说了 要去啊,引入你需要这个功能的, d l l 就 d l l 引入,怎么去引入啊?我刚刚写在这个这个里面了,然后我们对着它抄一下就行了。好吧,哎,对着它抄一下啊。呃,怎么去写?写在哪里?首先你要去, 首先你要去引入他的命名空间,他在哪里呀?在 system 点 run time, 点 interop services, 在这个里面,所以你就要需要在这个地方 using system 点 run time, 点 interop services, 在这个里面,然后呢,你要去引入他的 d、 l、 l, 那么在哪里引入?在他的类里面啊?在类里面敲一个回车,然后在这边写对中括号,写完了之后呢?他关键是 叫 import, 叫 d l l import 就这个东西,那这个是什么意思呢?你要引入的 d l、 l 是叫什么名字?就是它的文件名是什么? 是写在这里的,那么刚刚我们也看了,是吧?嗯, 这个图形接口叫什么? g d i 图形化用户界面,我们是不是在 g y 这边啊?就窗体啊这些,它是在 user 三二点 d、 l、 l 里面的,因为我之前已经查过它在哪里了,所以我知道你不知道,你去查一下 user 三二点 d l l。 好,这就引入完了,对吧?呃,引入完 完了之后,他为什么下面给你标红呢?是因为你可能还没有去声明他的函数啊。好,那这个怎么去声明? 它的声明方式跟我们声明普通的函数差不多,你看看区别在哪里啊?首先 private 开头 就是访问修饰符,对吧?然后这是一个外部的,我们要加个关键字 external, internal external 这种 extern, 然后是静态的,因为我们要在它里面去调用吧,是吧?静态的你不可能去扭一下。 好,那么这个函数它会给我们返回一个什么样的类型?没有返回类型,我们之间写 boy 的,对吧?有的话就写返回值类型,它会返回 一个 inter 类型的窗口标识符,全部都是数字,它有它自己特有的这个类型,叫 int p t。 啊,就这个返回一个,实际上这个就是 inter 类型啊,这就是 inter 类型, 它名字叫什么呢?这个名字是它在这个内裤当中,这个函数叫什么名字啊?叫 find window。 那同样它也有参数 是吧?啊?它也有参数,有几个参数呢?有两个,一个是 string 类型的 ip class name 就是类名,还有一个呢, string 类型的 ip window name。 好,就这个样子的。有人说你这样一写就可以用了吗?来,我们来试一下啊,我们不是这 获取句柄吧,我们把获取到的句柄放到这个里面来,写到内成员为止。 private interptr 是不是这个东西啊?这个类型啊? h 导个 n d, 先给它来一个空,就是零 into p d r 点 zero 就是零。它不是没有吗?你初始化的时候给它个零,对吧?当获取的时候呢?呃,你看一下啊, 把这个类成员拿下来就等于什么?等于去钓这个方法。 它的第一个参数类名我不知道,你可以写个空,第二个写个窗口标题就可以了,比如说回收站, 回收在就可以了。好,那么我们把它显示到那个文本框里面, this 点 text, h w n d 点 text, 等于把它拖一下 screen 就可以了。 呃,走你,你得到了一串数字,这个就是他的句柄,你就拿到他了,对吧?就拿到他了。那么怎么把这个窗口标题这边输进去让他拿过来呢?很简单啊,你把这个回收站改成 那个文本框的内容, this 点 text, title 点 text。 不要不要给他去除前后空格,因为万一别人的标题里面他带前后空格,那怎么办,对吧?好, 回收站获取巨屏是不是有啊?来,再来,这个 f o o b a r 两千空格 v 一点六点一二,不能错啊,一点错,错一点就不行了啊,获取一下是不是能获取到啊,对吧? 好,获取没有问题,那么我们怎么去修改呢?修改,你当然是用的另外一个函数,它由于 还是在这个 user 三幺里面,就是在用户界面这个里边,所以这个不变啊,这个不变,那它的入口点呢?就是一个 set window text, 上面呢?我们没有写入口点,他也调用正常了,对吧?哎,也调用正常了啊,那么你看看这个 private external static interlating set window text 这个能不能成?那么第一个呢?是还是这个类型?就是锯柄,你要传个锯柄给他。 第二个呢?呃,你要设置的文,这个这个窗口的标题是什么东西? 好,踏爆这个了。如果你启动的时候,他会告诉你运用程序处于中 段模式,也就是说你上面调这个,你要 d l l import 一下,你下面要使用它的话也需要去 import 一下啊,这样才可以。好吧, 好,我们这个设置标题拿过来判断一下,如果我们获取到的句柄不是这个的话,如果获取到的这个句柄不是 interpt 二点 zero, 那也就是获取到了,对吧?获取到这点了,你才可以去设置它, 那么去调动一下这个 set window text, 首先你要填个句柄进去,句柄在哪里啊?是不是刚才就这个东西啊? 好,你要设置谁的?然后呢?要设置什么标题?我是新的标题,好,看看可不可以啊?启动一下,我把所有东西都最转化,然后呢,打开回收站, 我获取回收站的据柄获取来了吧,对吧?设置标题呢?我们是不是要设置这个 text 里面的标题啊? 新的标题给它改成 this, 点 text new title 点 text, 回收站 获取是不?获取到了,我给大家看垃圾箱设置标题,好,你看这里没有变,对吧?啊?这里没有变,因为 vo 十一的 ui 它受这个底层 dla 的影响,但是你把这个鼠标移到这个回收站窗口上面去, 移过来,你可以看到,在这里啊,你可以看到他的标题已经变成垃圾箱了,对吧?哎,已经变成垃圾箱了,他这边只是没有显示出来。好,我们再来一遍啊,我们再来试一下,我打开这个 还是有播放器,好吧,因为它不是那种选项卡,这种看起来清楚一点, f o o b a 二两千空格 v e 点六点幺二获取,是不是能获取到啊?我是一个播放器的标题,好设置,看是不是改过来了, 标题是不是改过来了,对吧?当然你通过他还可以做好多事情,比如说我把这个窗口让他永远置顶,就像 qq 面板一样,他一直在这上面,是吧?然后我可以把这个窗口的形状啊等等,里面也可以找到某些空间啊,比如说我这个播放按钮, 播放按钮是可以点的,就有些东西它的功能是不能用的,比如说撤销、重做、清除、全选这些,是不是在特定情况下你才可以去使用它,对吧?那为什么呢?它就是把这个按钮做了个判断啊?如果 现在不是正在播放的这种状态,你就不可以去操作这些东西,对吧?啊?如果列表为空,你就不可以去操作,那你只需要去获取到这一个按钮的身份证,就是他的这个叫做呃句柄,然后把他的 enable 改成 two 就可以了, 他就变成可用状态了,对吧?但是变成可用状态不代表你可以去用他,你点他,他可能没有反应,或者是会保错, 明白了吧?嗯,有一些东西,比如说现在我们写的一些工具里面, 让他去查一下这个用户底下的这个客户,可是呢,你没有权限去查按钮是灰色的,那你可以通过这种方式把按钮给激活了,然后去查那种是可以的,对吧?所以 windows a p i 可以做做很多 事情啊,可以做很多事情。呃,用起来呢,也不复杂,但是你去学习 windows api 是一个非常复杂的过程。好吧,你不是所有的函数都像这个这么简单,有的函数里面他不是都不一定都是这种死菌类型的东西。 他还有一种你看不懂的,或者石榴金子的那些东西,你可能看着就比较头大。所以我为什么说新手喜欢去折腾这个?因为新手对这些东西比较好奇。 你如果工作很多年,从事跟 windows 有关的一些开发,你可能不会去好奇这个东西,因为太麻烦了。好吧,好,那这节课就到这里,拜拜。

大家好,今天我们来聊一个函数,可以说只要你写过代码,就几乎肯定用过它,但你真的了解它吗?咱们今天要深入聊的就是这个 sleep 函数。咱们就从一个最基本的问题开始吧,怎么才能让你的代码停下来?等一等, 这问题听起来简单,但答案嘛,可比你想象的要复杂的多。表面上看, sleep 函数的功能再清楚不过了,对吧?它就像一个暂停按钮,你想让程序等多久就告诉他一个时间,他就乖乖的暂停执行。 但事情没那么简单,这个看似无害的暂停按钮实际上是一把双刃剑,他看起来只是在暂停,但底下呢,其实是你的代码在和操作系统进行一场复杂的谈判。今天咱们就把这把剑的两面都看个清楚。 no, 这是我们今天的路线图。首先,我们会搞清楚这个暂停按钮到底是怎么工作的,然后看看大家一般都在什么地方用它。 接着,重点来了,我们会揭示它最大的问题,那个骗人的精度陷阱,以及它潜在的危险性。最后嘛,当然是看看除了 sleep, 我 们还有哪些更智能的选择。 好了,那我们就直接进入第一部分,看看调用 sleep 的 时候,电脑底层到底发生了什么。 你看,当一个县城掉了 sleep, 它可不只是在原地发呆,它其实是在主动跟操作系统的调度器说,哎,我先歇会儿,你把 cpu 时间给其他等着干活的县城吧。 这是一种非常绅士的行为,他主动让出了宝贵的 c p u 资源。好,既然我们知道了他的工作原理,那现实世界里,开发者们通常都拿它来干嘛呢? 其实他的应用场景还挺多的,比如说在测试的时候,我们可以用它来模拟网络延迟,或者在一些简单的游戏或者动画循环里用它来控制帧率。 当然了,还有一种用法,就是作为一个简单粗暴地用来解决多县城资源冲突的办法,虽然这么做风险不小。这是一个非常经典的例子,一个简单的游戏循环, 你看程序,先更新游戏逻辑,然后渲染画面,最后调用 sleep 三十三。 为什么要这么做呢?因为如果不加这个暂停,这个循环会以最快的速度疯狂执行,直接把你的 cpu 占满到一百。 通过暂停三十三毫秒,我们就能把帧率大致控制在每秒三十帧左右,既流畅又不浪费资源。好了,前面说的都是它的好处,现在我们得聊聊 sleep 的 第一个也是最核心的一个大问题了。 比如说,你现在想让你的代码就绷那么一小下,就暂停一毫秒,你以为他真的就只睡了一毫秒吗?嗯, 现实可没那么简单,实际上,你的代码很可能睡了差不多十五点六毫秒,甚至更久。 为什么呢?因为操作系统不是一个超高精度的秒表,它有自己的节奏,就像一个固定的时钟滴答声, 你的线尘睡着了,系统掉入器得等到下一次滴答的时候才会想起来要去检查一下哦,是不是有谁该醒了。所以,就算你只要求睡一毫秒,你也得等到那个下一个滴答点,而这个间隔在很多系统上默认就是十五点六毫秒左右, 你看你请求的时间和你实际得到的等待时间,两者之间的这个巨大鸿沟就是我们说的精度陷阱。 对于一些对性能和计时要求特别高的应用,比如实时音频处理或者金融交易系统,这种不确定性简直就是灾难。而且问题还不止于精度,滥用 sleep 甚至可能会直接搞垮你的应用程序。 这一点大家一定要记住,绝对绝对不要在主用户界面限程,也就是 u i 限程里调用 sleep, 你一旦这么做了,你的整个应用程序就会立刻被冻住,动弹不得,就是我们平时最讨厌看到的那个程序未响应的状态。 这里要搞清楚一个概念, sleep 只会影响调用它的那一个进程,而不是整个程序。也就是说,可能你程序后台的其他进程还在正常工作,但是对于用户来说,它看到的界面已经完全卡死了,点什么都没反应,这个用户体验可以说是糟透了。 除此之外呢,还有几个常见的坑,比如说 sleep 零,它的行为其实是不可预测的,只是让出当前时间片剩余的时间。 更要命的是 sleep infinite, 你 只要敢用,就会创造一个永远不会醒来的僵尸县城。当然,最最重要的一点是,千万别指望用 sleep 来做什么复杂的县城同步,它根本就不可靠,早晚会出问题。 好了,说了这么多 sleep 的 坏话,那问题来了,如果它这么多毛病,我们这些现代的开发者到底应该用什么来代替它呢? 咱们来看看这些更优秀的替代方案,比如说像 wait for a single object 这样的同步对象,它们是事件驱动的,它们等待的是一个明确的信号,而不是一段模糊的时间。 还有更现代的 a sync await 异步编程模型,它干脆就不会组测现成,现成可以去做别的事情,等任务完成了再回来。无论从精度还是效率上来看,这些方法都完胜此理。 所以说,现代平层的整个思路都变了。尤其是在云服务或者移动应用开发里,我们的目标不再是让程序暂停等待,而是构建事件驱动的系统, 让程序能够对各种事变做出快速响应。归根结底, sleep 就 像一把最基本的锤子,在某些简单场景下敲个钉子,它确实能派上用场。但如果你想构建一个健壮高效的现代软件,那你需要的就是一个更专业的工具箱了。 所以,下次当你准备写下 sleep 的 时候,不妨先问问自己,我的代码是真的只是需要睡一会儿,还是它能用更高效的方式来等待呢?

下面呢我们来介绍一下啊,这节课的重点,常用 a p i 函数的一个使用。首先我们来看一下啊,任务的挂起函数, 那么挂起指定的任务啊,被挂起的任务呢,绝对不会得到 cpu 的一个使用权,这个前面我们已经说了,不管这个任务具有什么优先级,那任务呢,可以通过调用这个函数 实现我们的任务的挂起,他可以将任务的不管是何种状态都能把它挂起。 这个在我们刚才介绍那张转换图当中也可以看到,不管你是就绪态,主色态,运行态,只要调用了我们的挂起函数,他都能进入到这个挂起态,进入到挂起态的任务呢,不绝永远不 会得到啊这个 cpu 的一个使用权,除非他又恢复啊,又通过这个函数来恢复他的其他的这种状态。 那我们来看一下这个挂起态,这个挂起这个函数啊,它的一个使用啊使用, 那么这个是函数的原型里面呢,有一个参数,这个参数呢,他是只要挂起了任务的任务句柄啊,我们在创建任务的时候啊, 会为每个任务呢分配一个任务句柄啊,这个在我们前面的实验当中我们都已经介绍了,如果说我们使用了动态内存啊,来创建我们的任务的时候啊,那么我们的这个函数的参数 啊,函数在这个函数创建任务的函数里面,就会有一个任务句柄的一个参数,所以呢这个就是我们的这个参数 啊,就是这个任务的句柄。那如果说我们使用的是这个静态方法来创建我们的任务的话,那么这个函数的返回值他就是任务的句柄,所以呢,我们可以通过这个呃这个函数啊,来一样可以把这个任务呢挂起啊, 那么任务的创建这个呢,还可以通过我们这个 a b i 函数来根据这个任务的名称获得我们的任务的句柄啊,所以说我们也可以通过调用这个函数来获取我们的任务的句柄,然后通过这个任务句柄传递到 这个函数 logo 参数里面,就可以实现任务的挂旗。那么注意啊,如果说我们给这个参数啊,给这个参数传递的是那啊空的话,那表示挂 挂起我们自身啊,我们就是我们自己的这个任务当前的任务,然后呢这个函数他是没有返回值的啊,这是我们的一个挂起任务的一个呃函数的一个使用,然后我们再来看一下 任务的挂起函数,还有一个是我们的这个这个函数呢,是将所有任务都挂起,那么它的一个代码呢,很简单里面就有一行啊, 其实呢就是将这个呃调度器啊锁定,这个函数呢,可以进行嵌套啊,可以进行嵌套,说白了呢,挂起所有的任务就是挂起任务的调度器,那么调度器被挂起之后呢,就不能进行上下文的一个切换,但是中断 还是使能的,那么当调度器被挂起的时候啊,如果有中断需要进行上下文切换的时候,那么这个任务呢就会被挂起,在调度器恢复之后啊,才能进行任务的切换。 那么如果说你使用了这个函数来挂起我们的所有任务的话,那么你要恢复,那么必须要调用对应的一个函数,也就是 x task issue 哦,同样的,它是配套的啊,这个是挂起所有,这是恢复所有,他们是 一对的啊,他们是一对的,所以你调用了多少次这个函数,你就要调用多少次这个来恢复啊,所以他们是一对应,从这个函数 里面的实线代码也可以看得到,他其实就对这个变量进行计数啊,计数啊,记录了多少次,调用了多多少次这个挂旗,那你恢复的话也是一样啊,恢复调调用多少次这个恢复函数, 这个任务的挂起啊,任务的挂起。那我们再来看一下任务的恢复,那么既然有任务的挂起,那么自然也会有任务的恢复,那么任务恢复啊,就是让挂起的任务呢,重新进入到就绪状态,那么恢复的任务啊, 他会保留挂起前的状态信息,在恢复的时候啊,根据挂起时的状态继续呢运行。那么如果被恢复的任务在所有就绪状态中呢,处于最高优先级啊,那么他会进行一个 啊任务的切换,实现将就绪任务转换成运行状态啊。那么我们使用的这个任务恢复函数呢?啊,原型是这个, 那么这个函数里面也有一个参数,这个参数呢就是要恢复的任务任务句柄,那当我们调用任务挂起的时候,传递的任务的句柄的时候,那我的任务就挂起了,那要恢复恢复的话,我们调用这个函数,给他传递同样的一个任务句柄,他就能恢复啊, 同样这个函数呢,是没有返回值的,这是任务的恢复啊,任务的恢复啊,任务恢复函数呢,除了这个之外,还有一个就是我们的这个中段啊,这两个函数区别之处就是一个适用于中段,在中段里面对我们的任务的恢复进行操, 而我们刚才看到的这个函数啊,它是适用于我们的普通任务啊,普通任务就是说在我们的中断里面,你不能调用这个函数来恢复我们的任务 啊,然后呢,在我们中断里面要调用恢复任务函数的话呢,那就是使用这个带 from i s r 的这个函数,在我们的 few r t s a p i 函数当中,凡是看到 fi from i s r 的话,它都适用于中断啊,都适用于中断。 同样这个函数呢,也是给他传递一个要恢复的任务的任务句柄,那么在这个函数里面有一个返回值, 那根据这个返回程我们可以看一下,如果是 q 的话,那么恢复运行的任务的优先级呢?等于或者高于正在运行的任务,那么被中断打断的任务啊, 这意味着呢,在退出中断服函数以后啊,必须进行一次任务的上下文切换啊, 那么我们还有一个返回值,如果是 force 的话,那么恢复任务的任务优先几呢?低于当前正在运行的任务, 那么这意味着呢,退出中段任务以后呢,不需要进行上下文切换。所以呢,在中段里面,我们调用这个恢复任务函数的时候,我们可以手动添加一个,呃,任务切换的一个代码啊,任务切换代码在我们前面已经介绍过,就是一个 y e i l d 啊,一个红啊,通过这个函数呢,实现他的一个任务的一个切换啊,手动的一个切换,那么这两个函数呢?都是啊任务的恢复函数,那么呃不,无论我们通过调用一次或 多次,我们的任务挂起函数的时候,那我们的任务被挂起,那么不管你调用多少次挂起,那么我们只需要调用一次任务恢复函数,就可以把我们的任务呢恢复啊。 如果说我们的任务没有被挂起的时候,你调用我们的任务恢复函数的话,他是没有任何意义的啊,这是我们两个任务恢复函数,那我们再来看一下任务删除函数, 任务删除函数呢?通过这个 a b i 函数来进行任务的删除,那么用于删除一个任务, 当一个任务删除另外一个任务的时候啊,那么这个行餐呢?要为删除任务创建时候返回的任务句柄,也就这个呢,是我们要删除任务的任务句柄,如果是删除自身的话,那我们给 给它传递个 n u l l 也就空,那么它就删除我们自身这个任务。那么要想使用这个函数呢,那必须要在我们的呃配置文件当中啊, 对,我们的这个啊, includ 那个红啊,进行字一,也就是我们删除任务的这个红进行字一啊,这个在我们创建工程模板的时候啊,已经全部之一了,所以可以不用去管它啊,本身就使用了这个任务删除函数,那这是任务的一个删除啊,也非常简单。 那么删除任务的时候啊,他只会自动释放内核本身分配给这个任务的内存, 而我们的应用程序分配给任务的任务内存或者是其他资源的话,那必须是删除内内任任务的时 时候呢由应用程序显示的释放,那么怎么去理解这段话呢?那么就好像我们在任务中呢,我们申请了一大块的内存, 但是没释放,就把这个任务删除了,那这一块内存呢,在任务删除之后,他不会自动释放,我们应该在删除任务之前呢,把这些资源呢释放掉,释放掉,然后再删除这个任务, 否则呢,他就容易造成内存的泄露啊,内存的泄露,这是我们任务删除的一个函数, 我们再来看一下任务的延时函数啊,任务函延时函数呢,有两个,一个是这个啊,另一个是这个,那这两个函数呢?我们分别来介绍一下。第一个, 第一个函数呢是在我们任务啊中呢,用的非常多啊,非常多,每个任务呢都必须是死循环,并且呢是必须要有主色的情况, 否则呢低优先级的任务他就无法被运行啊,被运行。所以呢,可以看到我们在前面的实验当中呢,我们的任务啊里面呢都会有一些延时啊,这个延时就起到了将我们的任务进入到主色状态,那么从而呢通过任务的一个调度器 切换到我们的其他任务进行执行啊,就不会说,如果说你在我们这个任务里面没有这个主色啊,就不会进入到主色,当我们这个任务 a 他的优先级是最高的话, 那你其他的任务就根本没办法执行了,因为你这里没有主色态,那任务就不会进 进行调度,他只一直在这里运行,那其他任务就没有工作,这就失去了我们的操作系统的一个呃意义了啊,所以呢,我们要在任务里面再选择一个合适的时间添加啊,我们的一个延时或者其他的就是将我们的任务呢记录到一个 堵塞状态啊,从而实现任务的切换,切换到其他的就绪列表啊,高音阶级的任务去执行 啊,这是我们的一个任务的一个延时,那么这里面呢参数呢啊,是一个传递的一个节拍啊啊,对于我们 few r t s 配载文件当中,我们已经将这个 节拍呢,就是说每秒钟运行一百个一千个节拍,也就是说一毫秒啊运行一次,所以呢我们传递这个值啊,就是代表着毫秒值, 比如说我们要延时一百个毫秒,那我们传递一百个节拍就可以了啊,这要注意的就是我们这个 d 类呢,它是一个相对性的一个延时,它指定的这个延时时间是从调用我们这个函数结束之后开始计算的,那么经过指定的时间呢啊,进行一个延时结束, 比如我们在调用这个函数的时候,我们传递的值呢是一百,那么从调用这个呃函数结束 后呢,进入我们的主色状态,那么经过一百个系统时钟节拍周期之后啊,任务的解除主色使用这种延时函数呢啊,他也有一定的局限性 啊,因为我们其他的任务或者中断服务啊,也会影响到这个 delay 它的一个调用时间, 比如我们调用高预线级的任务的时候,他就会抢占我们当前任务啊,从而呢影响他的一个节拍的一个执行,进而呢影响到任务的下一次的执行的一个时间啊, 这是这个相对延时的这个函数啊,不过呢我们对于没有说啊,对时间精度不是很高的情况下,那我们通常呢都是使用这个函数啊,都使用这个函数简单, 那我们再来看一下下面这个函数,下面这个函数呢,它是一个绝对的一个延时函数啊,绝对的延时函数,那么这个绝对的延时呢,常用于 比较精确的周期运行的任务,比如我有一个任务,希望他以固定的频率定期执行,而不受外部的影响,那从任务从上一次运行开始到下一次运行开始啊,他的一个时间间隔呢是绝对的,比如说我们从任务 a 啊到我们的任务 b, 我们必须保证一百个使用节拍,那我们就可以使用这个绝对的延时啊,延时的一个函数, 那么这个函数里面呢有两个参数,第一个呢是我们的这个上一次的一个呃时间,然后呢这个呢是我们的一个延时的一个啊,就是节拍,我们的一个节拍,因此我们在使用这个绝对 延时函数的时候啊,我们还要获取到我们的上一次的一个时钟,上一次的时间的话,节拍呢,那获取之后,再每一次就是加上我们这个需要延时的这个时钟啊节拍,才才能保证他的一个绝对的一个延时。 那么这个使用方法呢,大家可以看一下我们的开发攻略啊,里面就有这个函数的一个使用的一个举例啊,大家可以去看一下, 这是我们啊几个任务的一个啊,函数啊、挂旗恢复,还有删除延时啊这几个函数。

大家好,欢迎使用开胃控精灵。今天主要讲 api 函数使用第十五课 app 类中的意图 stard x 五应法 啊。这个赛的 x 五的话,他主要是通过迈步参数打开指定的 x 五,就是类似于我们安卓开发中的影视云吞的用法 啊。家人们看这个语法是直接通过 app 调用的。然后主要是讲这个里面的迈步参数。这个迈步参数的话,它是存放一组,具体的参数就是里面可以配置多项参数。呃,参数的形式也是 k v 六的形式 啊。首先看这个 k 神, k 神的话就是用来表现意图的这个行动。然后下面这个 u i, u i 的话就是通用资源标识符,就是代表我们要操作的数据啊,可以是 app, 也可以是费用,也可以是电话。然后泰普,泰普的话就是我们直接跟这个 ui i 的类型,还有 pakj 和克拉斯 m 是可以根据这个帮名和类名,然后打开对应的 i t 五。呃,最后这个 flag 是标准的 flag 标志 a。 然后我们下面两个例子来演示一下 啊。首先是这个,第一个就是自动拨号这个呃,里面配置了一个这个 action 和 ui 啊,他的意他这个 action 的话就是套上这个拨号界面。 ui 里面配置了这个电话,就是我们等会要自动拨号的这个电话号码。然后在下面下面这我们 app 点上的 it 五,然后传入了这个参数,我们来执行一下。好,他自动跳转到了这个拨号界面,这我手动清除一下, 再执行一次。他是自动拨号幺幺零零零啊。下面这个下面这个的话主要是呃,艾克逊和 ui 都变了,呃,是不同的这个意图。然后 ui 换成了一个 https 的网址,就是百度 这个。我们返回 直线上这个,打开百度这个网页, 他的话是自动打开这个浏览器, 然后下载百度这个网页。好,这个就是我们意图的用法。呃,这个可以选和 ui 的话,就是有很多种类,大家可以去网上这边搜索一下,是有很多种的。好,本节课内容就到这里,感谢大家观看。

大家好,欢迎使用开维控精灵。今天我们主要讲 api 函数,是第九课米点迷体类和所有的现成类。我们先来看这个媒体类。这个类呢,下面的函数主要是对应用设备的一些多媒体进行一些操作。 呃,先来看第一个函数,这函数这函数 please。 这个的话就是根据我们传入的这个路径来播放音乐。然后这个播放的话是不会显示任何播放界面。然后我们来演示一下。 好,然后我们这个文件下面有个根部,下面一个 aa 的文件夹,里面是有一个 mp 三。嗯,可以先看一下这个。 这话就是一首音乐,差不多三分钟。 好,我们用这个演示一下。呃,接下来看我们的代码。首先是第一步调我们这个函数,传入一个路径,就是我们这首这个 m b 三的这个路径。呃,我们传进去,然后让他播放,延迟五秒。之后我们调用下面这个。呃,这个函数的话是也是在米粒二。下面 这个当兵用力可就是停止音乐的播放。好,来演示一下。 点击直行,他会播放五秒之后啊,停止播放。 哦,这是这一个。呃,除了这个 stop, 那个停止音乐播放,上面还有一个对应的这个暂停音乐播放。它的区别就是 stop 的话就是直接把这个音乐停止了。呃,播放的话只能重头播放了。然后这个暂停播放的话,就是相当于中断了一下。呃,调用完这个暂停播放之后,我们可以再调用下面这款数。这款数啊,是继续音乐播放,从我们中断地方开始再次播放。 这个我们来演示一下 啊。首先还是我们传入滤镜,开始播放这首音乐,然后延迟这个延迟,我们让他延迟短一点, 延迟五秒之后,呃,电容下面这个 pose。 music 就是暂停音乐的播放, 然后暂停三秒,三秒之后我们再次这个调用这个继续音乐播放。就是我们对应的这个函数,他可以 也从中南地方再次播放。然后延迟五秒之后,我们最后是停止音乐的播放, 来演示一下,这是暂停。 接着播放, 最后是停止播放了。 这是这几个啊,接下来我们从头讲。呃,第一个函数的话就是返回当前音乐的播放进度,就是已经播放了多长时间,在这个时间的话,单位是毫秒。这个来演示一下。还是以这个 mp 三为例 啊。首先是播放这个 mp 三,然后延迟五秒之后我们获取他播放的时长,就是差不多五千毫秒那个时间。然后再播放五秒之后我们停止播放。 我们调用这函数的话,是返回一个变量,复制给这个变量,点击执行。 注意看这里。好,就是五秒左右一个数值。 好,接下来我们看一下下面这个函数,这个函数是返回当前音乐的时长,就是这首歌大概就是总时长是有多少秒,他单位的话 也是一个毫秒 啊。这个先看我们这个代码。呃,首先是播放这首音乐,延迟两秒之后,我们获取这个音乐的总时长,然后把它打印出来,最后停止播放, 点击直行。好,注意看这里差不多是两万多毫秒,两万两千多毫秒,呃,也就是三分钟多。对于我们这个里面这个他是总时长三分四十四秒。 好,接下来看下面这个函数。 这个的话就是返回当前是否在播放音乐,他反映的话是一个布尔直这个 表演试一下。 呃,首先还是播放音乐,然后 呃通过我们调用这个函数判断他是否正在播放音乐,因为这个是在播放中的,所以他应该会返回一个处。然后在最后我们调用了这个扫描这个停止音乐播放,然后在他后面我们再调一次是否在播放音乐,这个时候的音乐已经停止了,所以他应该反馈的是一个放肆 点击直行。两秒之后啊,他返回就是处,说明这个时候正在播放, 有延时原出嘛,之后暂停着音乐放,所以他返回是一个 force。 好,大家看一下,现在是处 好才是这个 first 下面这个函数。下面这个函数呢,就是把当前播放进度调整到时间这个的位置,就是相当于呃拖拽了这个进度条他的单位的话也是一个好秒数,就是音乐的进度。 看这个代码,代码的话首先是还是播放这个音乐,然后播放三秒之后我们让他调整到呃调整这砍数调整到两万二秒,两秒呃二十秒处。然后我们延迟三秒之后停止播放。 这个我们可以听一下, 点击直行, 要想青山低可吞 啊,就是这样。好,下面这个暂停音乐播放。我们讲过了, 这个是播放音乐。还有这个的话就是播放音乐文件,然后他有两个选项可以选择音量和是否循环播放,他也是不会显示任何音乐播放界面的。然后这个这个播放音量的话,他是有一个范围是零到一点,零到一的分点数,默认的话是一。 我们来演示一下这个播放的话他声音是比较小,就算是一,就是最高的话他也是稍微小一点。点击,我们在这里加一个延迟 点击直行五秒之后大家暂停。呃,停止了,不是暂停。 然后的话我们这里也可以选择一个这个是否循环播放。呃,就是最后这个参数啊,是可以调成处的,处的话就是可以让他循环播放。 这个你就不再演示了啊。下面这个 play ui music。 这个话就是播放视频文件,刚才我们播放的是音频文件,然后也是可以选择是否新闻播放的 哦。这个的话我们以也是这个文件下面的一个 mp 四,点进去看一下这个视频为例。 视频的话差不多十秒钟。 他使用的话也是很简单,直接传入这个路径就可以了。 好,我们将这卡数,然后插入我们这个 mp 四的路径,点击直行。好,可以看到他是开始播放。 好,播放完成。 这个是波兰 p 四的啊。下面最后这一个函数。这个函数啊就是扫描我们传入这个 pass 啊。如果他是图片或者音频,什么就是媒体文件的话,是可以把它加 倒入到魅力库中呢。这个魅力库的话就是指我们的这个音乐库或者相册啊。这个话就是我们可以先传入一个路径,然后把这个路径扫描,扫描到我们的相册里面。 这个话就不再演示了,因为我这台机器的话,他是自动的将我们这个文件中的一些媒体文件扫描到我们的媒体库。好,接下来我们来演示这个。我们讲一下这个 c 的现成类,所以说现成类的话,这个重新连接一下, 他主要是对县城的一些操作。 好。接下来我们来讲这个所谓的县城类,这个类的话就是主要对县城一些做一些操作。我们先看下面这砍树,这砍的话就是启动一个新的县城,然后并且执行我们里面这个方队上函数,然后这个我们可以演示一下 啊,可以看到我们这个代码中,我们通过这样撒的这个函数,我们开了两个新的县城,然后在这两个县城中,我们都是都是打印从零到四这几个数字,我们看一下, 点击执行。我看这里先是现成二,我现在一 好,这样应该就打印完了啊。我们可以在这个执行过程中可以看到这个函数,这个函数啊就是停止所有通过这个塞纳函数启动的这个子线程,就让这些子线程的话就都是这个停止运行量, 这个就不再演示了。接下来我们看上面这个函数,这个函数的话就是返回当前线程,这个我们演示一下, 点击执行。这里我这里是直接打印了出来这个现成的一些信息, 看下一个这个线程的话是返回主线程,这个我们再打印看一下,点击直行, 他返回的是我们当前的主线,整 下面这个县城,这个县城。呃这个这个函数的话是判断当前是否有运行的县城,他仿一段是一个布尔直,就是是否有是否有运行的县城。这个我们看一下, 点击直行,他返回处说明是我们当前是有一个县城的,那就是我们的主县城。好,本节课内容就到这里,感谢大家观看。

大家好,今天呢我们讲一下清空回收站中的文件啊,清空回收站是 windows 呃我们经常使用的一个功能,呃,那么呢,我们怎么让自己写程序来清空回收站呢? 哎,我们今天主要是呃通过讲这个例子啊,让大家了解一下系我们怎样调用系统的 a p i 函数。 首先呢还是打开我们这一个编程的工具啊,如果大家没有这个工具呢,可以 哎,看我们第一个和第二个视频进行下载和安装,我们创建一个项目清空回收站, 那么呢我们呃这个实例呢,这个例子呢,也就是呃大家没有其他的一个基础的时候,也可以照着我们的视频来写。 现在我们呃新建了一个项目,然后自动创建了一个窗体,我们可以把这个窗体呢,呃设置为居中显示,然后把它的 文本啊标题设置为清空回收站, 那么呢我们这个程序就只有一个按钮啊,给他去按钮的名称呢,就是清空回收站。好, 那么呢,哎,双击写它的 click 事件啊,嗯,这里呢我们先定义几个常量,首先第一个啊, 这个呢就是 哎表示我们清空的时候不显示那个确认对话框,就是 删除清空时不显示确认对话框。 这个呢就是我们清空的时候呢,不显示 那个不显示进度条, 这个就是没有声音,我们正常呃删除的时候啊,删除清空回收站的时候呢,呃他会显示一个那个呃声音,那么我们这个把它设置为 删除完毕,删除完毕复播放 声音。 好,然后呢我们再调用一个申明一个 a p i 的函数啊,先调用系统的。 好,我们这里呢可能还要引用一个运行命名空间。 好,这个一些,呃, v p i 的声明呢?啊,都已经设置好了,那么我们再写这个清空回收站的这个代码,这个代码就很简单了, 这个 g b。 好,那我们再看一下啊,现在呢,我们这个回收站里面啊,他是没有清空的,我们运行 测试一下啊。哦,运行不成功, 我这里少写了一个符号。 好,那么我们现在点清空回收站,我们注意看一下啊,好,这里面的内容就清空了。 好,那么我们再测试一下。哎,把这个纸改一下,改成了,呃,然后我们现在这两个文本文档把它删除之后,这两个文件啊放到回收站里面,现在回收站又有内容了, 我们再来运行一下。好,我们点清空,这这个里面他就和我们平时清空 样啊,就有这个提示了,哎,然后就清空了,那么呢,我们今天主要是通过写 那个清空回收站的程序呢,哎,给大家演示一下怎么样来调用系统里面封装好的 vpi 函数。哎,这个系统封装的 vpi 函数呢,有很多功能。 哎,那么我们,哎可以通过在网上查一些资料啊,哎,自己通过我们写程序来调用,这个用起来是很方便的啊。

大家好,欢迎使用开微控制精灵。今天主要讲 api 函数。使用第十七个匹配坐标一算值。完成这个功能的话是需要多个函数组合使用。第一函数我们用的是这个全球函数里面的开始卡拉,这个函数是获取坐标点的一侧值, 他返回的一个颜色直的话是是六进制的,然后是自负超类型的一个格式。第二函数我们用这个卡拉尔颜色类里面的依靠参数,这个函数功能的话是比较两个颜色值是否相等,反应的话是一个波尔类型的, 他是里面修的颜色值的参数的话就是这种以警花开头,然后颜色字不差类型的。所以我们等会该卡了。而获取的颜色值是需要转换一下才能进行比较的。然后演示是以这个游戏为例,先进入到这个游戏。 嗯,这个时候啊,因为这个游戏版本更新,他出出现了一个弹框,是需要点击这个取消或者更新才能跳过这个弹框的。然后我这里选择点击这个取消。 嗯,做法的话是我们可以进入到这个游戏之后,用刚才这个该开了这个函数获取大概这个点的一个颜色值, 让这个颜色值和我们预期的颜色值就是这个绿色挺比较。呃,如果是相等的话,就说明他有这个弹窗,是我们可以点击模拟点击做个腰,然后点击取消跨过这个弹框的。如果不相等就是不需要更新,直接跳过就行了。 好,接下来我们来写这个代码。呃,我们第一步定这个该他开了。这个函数是需要截屏权限的,所以我们需要先写这个 呃奥多效的 skry 身体结截屏权限。 然后第一步我们进入到这个游戏 啊,刚才进入这个游戏之后,他是有一个几秒的加载时间,所以这里延迟几秒。 你们先进入了手动进入这个游戏。 呃,我们可以通过这个节能工具获取大概这个点的一个坐标, 鼠标放到这个位置。呃,右上角的话是会显示他一个左边点。 好,接下来我们需要钓上这个改刀卡拉。这个函数 大概是七三四四五四。 我们刚才讲这个颜色值,他是一个十六进制的租车类型,所以需要转换一下。首先的话我们可以调用这个卡拉尔颜色类里面的一个兔子 这个函数。这个函数的话就是我们将颜色值转成这种。呃,请号开头颜色就是串类型。然后他这个需要的参数的话是一个数值类型。所以我们第一步需要先把这个卡特卡拉获取的颜色值转换成数值类型,然后再听这个卡拉点 toos tree 转成这种格式的一个颜色值。 我们用一个边量接一下,调用卡拉点儿 toss train。 然后里面的数值类型的话是需要一个数值类型的,就用这个 passine 哦。这行的话就是先获取这个左边脸的颜色值,然后将这个 pose 印的把它转换成一个数值类型的。 然后最后再用电用这个卡拉点 tuostry 转成这种以井号开头颜色字不串类型的。或许之后我们可以先把它打印出来获取一下。就是为了方便我们后面进行比较,打印到这个控制台上。 好,我们这里先执行一下获取这个颜色值。 大概是这个颜色,你把它复制下来, 前面有个井号,这个控制蓝化就是不再需要了。嗯,或许这个颜色之后我们进行比较,调用这个伊克的方法,它反应的话是一个 poar 类型的,所以我们可以用一个瑞遭的接收一下。 嗯,里面两个颜色金比较。第一个话传入我们这个获取的一个颜色值。第二个参数获取我们呃,传入我们这个逾期的颜色值。 然后拿到这个结果之后,我们判断一下啊,如果他是相等的话,就说明有这弹窗,我们可以调用这个模拟坐标,点击 点击这个取消,让他跳过去。如果没有不相等的话,就是直接列过跳过就行了。 就用这个四 s 店 most click 穿一个左标值多半的话,我们就穿过冠军获取的这个。 点击完之后,我们答应一句话, 如果不想的话,我们也打一句话 yeah! 好。这样我们这个整个大码就变写完成了。先手动把这个关一下,这里来执行一下,先进入到这个游戏,延迟几秒。 好,他这样的话就是自动点击这个取消弹窗,进入到这个游戏主界面了啊。本节课内容就要到这里,感谢大家观看。

今天分享一下插入二维码的第三个方法,要用网络提供的 api 接口,首先要了解一下什么是 api 接口。 api 的全称是 application programming interface, 翻译过来就是应用程序接口,你可以把它简单理解为一个函数,只不过这个函数里边的原码我们看不到,只能看到它的参数,通过输入指定的这些参数就可以返回需要的结果。至于函数内部是如何实现的,我们不用管, 关于 api 的详细定义,大家可以自己搜一搜,这里就不再赘述了。一般情况下, api 都会提供一个使用说明,告诉我们这个 api 的作用是什么,有哪些参数, 通常还会举几个例子,所以 a p i 的使用相对来说还是比较简单的。今天的主角就是这个二 二维码的 api。 首先我们打开这个网站,看一下它里边的使用说明,这个网站全部都是英文的,不过大家不用担心,我们的微微输入法带有翻译功能,所以我带大家快速过一遍。首先看这里,第一部分 翻译过来就是目录,也就是说他主要分为三大块,第三部分很容易看出来是一些参数,然后我们先看第一和第二部分,这是第一部分什么服务,然后我们翻译一下他是服务条款, 然后再把这一段翻译过来,它的大概意思就是这个 a p i 是免费的,并且每天可以访问一万次。然后第二部分快速开始快速入门指南,然后再看 下边这一段话,就是可以发送一个 get 请求,获得 png 格式的二维码图片。这里是一个模板,一共用到了两个参数,第一个参数 data 是编译过的文本内容,第二个是大小,是像素乘以像素, 然后下边他举了一个例子,说的是可以让我们直接试一试下边的这个链接,我们重新打开一个网页, 可以看到它就是刚才的二维码,内容就是 hello word。 然后再往下边这部分说的是可以在 h t m l 里边直接用 image 标签来使用这个图片, 所以待会我们写代码的时候插入二维码图片,我们也可以直接用插入图片的方法,而图片位置就是这个链接。 第三部分是参数,其实这里边的参数我们主要用到的只有两个,一个是 data, 一个是 size, 就是内容和尺寸,其他的这些参数都是可选的,都是一些什么背景颜色之类的,大家可以自己看一看。 现在来看一下 vba 代码应该怎么写。第一种方法就是直接插入二维码图片,我们用到两个函数,第一个就是编码函数,第二个是插入图片函数,这两个在上一期的视频都介绍过了, 插入二维码的时候很简单,直接调用插入图片的函数,图片的位置就可以写 api 的网址,然后把它插入到 b 一单元格,现在我们来运行一下, 可以看到这个二维码就插入了,假如说我们想要把二维码图片下载到本地, 就需要用下面这个方法,同样他也用到了这个编码函数,然后发送一个 get 请求,这个是 a p i, 然后获取数据,再把获取到的数据转换为图片格式存到本地,这样就可以了。我们来试一下 直接运行这个代码,可以看到二维码就下载到当前的文件夹里面了。 使用这个 api 和上期分享的网抓的方法都有相同的缺点,第一就是需要有外网,第二就是他的速度会受到网络的影响会比较慢。 那有没有一种方法既简单速度又快,而且还不需要联网?这种方法是有的,下期我们揭晓插入二维码的最终方法。