《Windows API每日一练》7.1 计时器基础知识

计时器(Timer)是一种在编程中用于测量时间间隔的机制。它允许程序在指定的时间间隔内执行特定的操作或触发事件。

本节必须掌握的知识点:

        计时器

7.1.1 计时器

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

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

       ■Windows系统计时器

在 Windows 系统中,计时器的实现原理涉及到系统时钟和消息循环。

Windows 系统中的计时器通常使用以下两种方式实现:

●基于时间片的计时器(基于轮询):这种计时器的实现方式是在应用程序的消息循环中以固定时间间隔进行轮询。应用程序通过在消息循环中处理 WM_TIMER 消息来执行特定的操作。WM_TIMER 消息会周期性地发送给应用程序的消息队列,以通知计时器事件的发生。

应用程序可以使用 SetTimer 函数来创建一个定时器。该函数指定计时器的时间间隔和回调函数,并返回一个计时器 ID。然后,在消息循环中,应用程序通过处理 WM_TIMER 消息来执行相应的操作。

这种基于时间片的计时器适用于较低精度的计时需求,例如执行周期性的任务或更新用户界面。

●高精度计时器(Multimedia Timers):对于需要更高精度和准确性的计时需求,Windows 提供了高精度计时器。高精度计时器使用系统时钟的硬件定时器来实现,提供了更高的计时精度。

应用程序可以使用 timeSetEvent 函数来创建一个高精度计时器。该函数指定计时器的时间间隔、回调函数和其他参数,并返回一个计时器 ID。计时器事件触发时,系统会调用指定的回调函数。

高精度计时器适用于需要更精确计时的场景,例如音频和视频处理、实时数据采集等。

无论是基于时间片的计时器还是高精度计时器,它们的实现都依赖于系统时钟和消息循环。系统时钟提供了时间基准,用于确定计时器事件的发生时间。消息循环负责接收和处理计时器相关的消息,以便应用程序可以在计时器事件发生时执行相应的操作。

需要注意的是,计时器的精度可能受到系统负载、硬件性能和操作系统版本等因素的影响。因此,在实际应用中,如果需要更高精度的计时器,可以使用高精度计时器,并进行适当的性能测试和调优。

基于时间片的计时器

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消息。

       ■计时器同步

因为计时器是基于硬件计时器的中断,程序员有时会被误导,认为他们的程序可能会被异步中断打断后被迫去处理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消息。但是请记住,这些消息不是精确的时钟滴答中断。

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值