8.1 计时器的基本知识_计时器的一排一道是什么意思_wiljm的博客-程序员信息网

技术标签: 编程  计时器  windows  时钟滴答  《Windows 程序设计》学习之旅  

摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P263

        你可调用 SetTimer 函数为自己的 Windows 程序分配一个计时器。SetTimer 包含一个无符号整型参数,该参数指定了时间间隔的长短,为一毫秒(millisecond)到 4294967295 毫秒(将近 50 天)。这个参数也表示 Windows 给程序发送 WM_TIMER 消息的频率。例如,1000 毫秒就是要求 Windows 每一秒钟向你的程序发送一条 WM_TIMER 消息。

        当程序不在需要计时器时,它可调用 KillTimer 函数停止计时器的消息。在处理 WM_TIMER 消息时调用 KillTimer 函数可以实现一个“一次性”的计时器。KillTimer 函数会清除消息队列中任何没被处理的 WM_TIMER 消息。调用了 KillTimer 之后,程序就不会再收到 WM_TIMER 消息了。

8.1.1  系统和计时器

        Windows 的计时器只是简单地扩展了 PC 硬件和 ROM BIOS 中的计时逻辑。回到 Windows 之前的MS-DOS 编程时代,应用程序的时钟计时器功能是通过截获一个叫“时钟滴答”的 BIOS 中断而实现的。这个中断每 54.925 毫秒出现一次,或每秒出现 18.2 次。这是由原始的 IBM PC 的微处理器时钟频率 4.772720 MHz 被 2^18 整除而得到的。

        Windows 的应用程序并不截获 BIOS 中断。Windows 本身会处理硬件中断,应用程序不需介入。对于当前所设定的每一个计时器,Windows 都会保持一个计数值,硬件时钟滴答每出现一次,这个值会减 1。当计数值减到 0,Windows 会把一个 WM_TIMER 消息放到适当的应用程序的消息队列中,同时把计数值重新设置回它的原始值。

        由于 Windows 应用程序是通过正常的消息队列来接收 WM_TIMER 消息,所以你绝对不用担心程序在处理其他任务时会被突然而来的 WM_TIMER 消息所“中断”。因此计时器与键盘和鼠标相似:驱动程序会处理异步硬件中断事件,Windows 则将这些事件转换为有序的有组织的系列化的消息

        在 Windows 98 上,计时器具有与底层 PC 计时器相同的 55 毫秒的周期。而在 Windows NT 上,计时器的周期大约是 10 毫秒。

        Windows 应用程序不能接收比上述频率更高的 WM_TIMER 消息,也就是说在 Windows 98 上约为 18.2 次,而在 Windows NT 上为每秒 100 次。Windows 会通过 SetTimer 把指定的时间间隔舍入到时钟滴答的整数倍。例如,1000 毫秒时间段被 54.925 除是 18.207 个时钟滴答,它被舍入到 18 个时钟滴答,因此实际的间隔是 989 毫秒。如果时间间隔被设置为少于 55 毫秒,每个时钟滴答都将产生一个 WM_TIMER 消息

8.1.1  计时器消息不是异步的

        因为计时器是基于硬件计时器的中断,程序员有时会被误导,认为他们的程序可能会被异步中断打断后被迫去处理 WM_TIMER 消息。

        其实 WM_TIMER 消息并不是异步的。WM_TIMER 消息被放在正常的消息队列中,并和其他的消息一同排队等候处理。因此如果你在调用 SetTimer 函数时指定 1000 毫秒,并不能保证程序每秒钟或者每 989 毫秒(如我前面说过的)就收到一个 WM_TIMER 消息。如果你的程序处于忙的状态超过一秒钟,它就会在那个时间内得不到任何 WM_TIMER 消息。本章提供的程序便是证明。事实上,Windows 处理 WM_TIMER 消息和处理 WM_PAINT 消息很类似。这两种消息都是低优先级的,只有当消息队列中没有其他消息时,程序才会收到他们

        WM_TIMER 消息还在另一方面与 WM_PAINT 消息极为类似。Windows 并不会连续不断地产生多个 WM_TIMER 消息到消息队列中。相反,Windows 把在消息队列里的多个 WM_TIMER 消息结合成一条消息。这样,应用程序不会同时收到大量的 WM_TIMER 消息,尽管它可能会收到靠得很近的两个 WM_TIMER 消息。同时,应用程序并不知道有多少这样的 WM_TIMER 消息在这个过程中“丢失”了

        因此一个时钟程序不能通过计算它所收到的 WM_TIMER 消息个数来确认已过去多长时间。WM_TIMER 消息只能告诉应用程序,更新的时间到了。在本章的后面,我们会写两个时钟程序,它们每秒钟更新一次,我们将准确地看到它是如何实现的。

        为方便起见,我将假设计时器每秒钟收到一个 WM_TIMER 消息。但是请记住,这些消息不是精确的时钟滴答中断。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013678930/article/details/49491377

智能推荐

MySQL数据库高可用集群搭建-PXC集群部署_jijinduoduo的博客-程序员信息网

Percona XtraDB Cluster(下文简称PXC集群)提供了MySQL高可用的一种实现方法。集群是有节点组成的,推荐配置至少3个节点,但是也可以运行在2个节点上。PXC原理描述:分布式系统的CAP理论:C:一致性,所有的节点数据一致A:可用性,一个或者多个节点失效,不影响服务请求P:分区容忍性,节点间的连接失效,仍然可以处理请求其实,任何一个分布式系统,需要满...

Python爬虫知识(3)—— xpath 选择器_限累万b282fd_HeatDeath的博客-程序员信息网

<!DOCTYPE html> <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]--><!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]--><!--[if IE 8 ]> <html lang="en" class="no-js ie8">

ps 抠图 选择并遮住_香椿遇上蛋的博客-程序员信息网

选择套索工具,将需要扣取的羽毛框选出来点击 选择并遮住使用第二个画笔,“调整边缘画笔工具”,涂抹细节,并勾选净化颜色可以添加一个背景,将会看到羽毛被扣取出来了...

ThinkSystem操作系统安装指导 – RedHat Enterprise linux 7.3(RHEL8可参考)_sr588系统安装加载驱动_imin_Q的博客-程序员信息网

ThinkSystem操作系统安装指导 – RedHat Enterprise linux 7.3目的步骤1、介质准备,根据用户环境选择2、RAID驱动准备3、UEFI/BIOS配置4、RAID配置5、 操作系统安装6、 驱动下载目的为了帮助大家使用U盘或者光盘进行手动安装Red Hat Enterprise Linux 7.3。步骤1、介质准备,根据用户环境选择U盘安装方式:先使用刻录软件将U盘制作成Red Hat Enterprise Linux 7.3安装盘。光盘安装方式:准备安装光盘、

解决use -D_SCL_SECURE_NO_WARNINGS的问题_use -d scl_每天看一遍,防止恋爱&&堕落的博客-程序员信息网

vc2012报错了:1>c:\program files (x86)\microsoft visual studio11.0\vc\include\xutility(2176): error C4996: 'std::_Copy_impl': Function callwith parameters that may be unsafe - this call relies on the ca

随便推点

JAVA-通过Calendar获取报表按日、周、月分组的时间轴_java获取时间轴_CSYZA的博客-程序员信息网

在报表需求中,经常需要按日、周、月分组,但是如果某段时间没有对应的记录,时间轴会不连续我们可以使用JAVA的Calendar来预设某段时间的时间轴传入时间区间,获取轴直接上 代码。public class DateUtil { // 当然入参也可以换成localdate、date等类型,出参也可以换成月-日等 /** * 获取day1到day2的周间隔 * @return */ public static List&lt;String&gt; getW

ctf.show_web8(脚本问题)_偶尔躲躲乌云334的博客-程序员信息网

这道题是我第一次用py脚本做题,收获真的很大,虽然过程非常艰难第一步判断注入点类型由于SQL恒不成立, 数据库查询不到任何数据, 从而导致页面空显示所以判断这是数值型注入从这可以看出过滤了and 接下来进行脱库, 由于盲注脱库比较复杂, 此处我们构造Python脚本进行自动化脱库, 注意payload中的字符串不要换行, 否则可能会出问题 查询了数据库名 查询表名,猜测在flag表中 查询字段名这里有个要点, table_name=0x666C6167这里是表名等于flag,flag

git push gerrit 常用命令_洛克Lee的博客-程序员信息网

需要Review(走Gerrit)git push origin HEAD:refs/for/dev-d711不需要Review(直接推)git push origin HEAD:refs/heads/branchgit reset --hard commitId 完全恢复到某个提交版本git push origin master:refs/for/masterorigin 远程仓库名称master 分支名称refs/for/master 远程分支名称

【友云音】【问题排查记录-5】中间件启动异常_yonyou-yyy-agent_Z.Virgil的博客-程序员信息网

问题现象NC中间件启动时一直卡在这个界面不进行加载。问题分析1、查看了ncSysconfig,发现了客户的jvm参数有一段异常。客户在部署的时候少填写了一段jar包。造成中间件启动异常。上面是正确写法,下面是异常填写。修改后启动正常。2、后续客户加上友云音的jvm参数后,发现中间件启动异常缓慢,之前启动中间件5min左右,现在启动了10min还在继续。于是查看了客...

Java 学习之路(与C、C++和Python对比)(持续跟新)_思简行繁乃成的博客-程序员信息网

变量Java,是强类型语言。1.变量必须先声明后使用。2.相同类型的变量才可以相互操作。(不同?强制转化!)输出System.out.print("中文");System.out.println("中文");//自带换行输入Scanner in = new Scanner(System.in);//必须写String str = int.nextLine();//读入字符串...

WebClient 用法总结_webclient的用法_doubleicon的博客-程序员信息网

一、WebClient概述   WebClient提供向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法, WebClient 类提供向 URI 标识的任何本地、Intranet 或 Internet 资源发送数据以及从这些资源接收数据的公共方法。   WebClient 类使用 WebRequest 类提供对资源的访问。WebClient 实例可以通过任何已向 We

推荐文章

热门文章

相关标签