定时器常常用于通信协议中。例如,如果客户机向服务器发出一个请求,而服务器没有在规定的时间内作出响应,那么客户机就会认为无法使用服务器。目前,客户机通常要同时与许多服务器进行通信。如果你为每个请求创建一个定时器内核对象,那么系统的运行性能就会受到影响。可以设想,对于大多数应用程序来说,可以创建单个定时器对象,并根据需要修改定时器报时的时间。
定时器报时时间的管理方法和定时器时间的重新设定是非常麻烦的,只有很少的应用程序采用这种方法。但是在新的线程共享函数(第11 章中介绍)中有一个新函数,称为C r e a t e Ti m e r Q u e u e Ti m e r,它能够为你处理所有的操作。如果你发现自己创建和管理了若干个定时器对象,那么应该观察一下这个函数,以减少应用程序的开销。
虽然定时器能够给A P C项进行排队是很好的,但是目前编写的大多数应用程序并不使用A P C,它们使用I / O完成端口机制。过去,我自己的线程池中(由一个I / O完成端口负责管理)有一个线程,它按照特定的定时器间隔醒来。但是,等待定时器没有提供这个方法。为了做到这一点,我创建了一个线程,它的唯一工作是设置而后等待一个等待定时器。当定时器变为已通知状态时,线程就调用P o s t Q u e u e d C o m p l e t i o n S t a t u s函数,将一个事件强加给线程池中的一个线程。
最后要说明的是,凡是称职的Wi n d o w s编程员都会立即将等待定时器与用户定时器(用S e t Ti m e r函数进行设置)进行比较。它们之间的最大差别是,用户定时器需要在应用程序中设置许多附加的用户界面结构,这使定时器变得资源更加密集。另外,等待定时器属于内核对象,这意味着它们可以供多个线程共享,并且是安全的。
用户定时器能够生成W M _ T I M E R消息,这些消息将返回给调用S e t Ti m e r(用于回调定时器)的线程和创建窗口(用于基于窗口的定时器)的线程。因此,当用户定时器报时的时候,只有一个线程得到通知。另一方面,多个线程可以在等待定时器上进行等待,如果定时器是个人工重置的定时器,则可以调度若干个线程。
如果要执行与用户界面相关的事件,以便对定时器作出响应,那么使用用户定时器来组织代码结构可能更加容易些,因为使用等待定时器时,线程必须既要等待各种消息,又要等待内核对象(如果要改变代码的结构,可以使用M s g Wa i t F o r M u l t i p l e O b j e c t s函数)。最后,运用等待定时器,当到了规定时间的时候,更有可能得到通知。正如第2 7章介绍的那样,W M _ T I M E R消息始终属于最低优先级的消息,当线程的队列中没有其他消息时,才检索该消息。等待定时器的处理方法与其他内核对象没有什么差别,如果定时器发出报时信息,而你的线程正在等待之中,那么你的线程就会醒来。