不论在客户端应用程序还是服务器组件(包括窗口服务)定时器通常扮演一个重要的角色写一个高效的定时器驱动型可管理代码要求对程序流程有一个清晰的理解及掌握NET线程模型的精妙之处NET框架类库提供了三种不同的定时器类SystemWindowsFormsTimer SystemTimersTimer 和SystemThreadingTimer每个类为不同的场合进行设计和优化本文章将研究这三个类并让你理解如何及何时应该使用哪一个类
Microsoft? Windows?里的定时器对象当行为发生时允许你进行控制定时器一些最常用的地方就是有规律的定时启动一个进程在事件之间设置间隔及当进行 图形工作时维护固定的动画速度(而不管处理函数的速度)在过去对于使用Visual Basic?的开发者来说定时器甚至用来模拟多任务
正如你所期望的那样对于你需要应对的不同场合微软为你装备了一些工具在NET框架类库中有三种不同的定时器类SystemWindowsFormsTimerSystemTimersTimer和SystemThreadingTimer头两个类出现在Visual Studio? NET的工具箱窗口这两个定时器控件都允许你直接把它们拖拽到Windows窗体设计器或组件类设计器上如果你不小心这就是麻烦的开始
Visual Studio NET工具箱上的Windows窗体页和组件页(见Figure )都有定时器控件非常容易的错误地使用它们当中的一个或者更糟糕的是根本意识不到它们的不同仅当目标是Windows窗体设计器时才使用Windows窗体页上的定时器控件这个控件将在你的窗体上放置一个SystemsWindowsFormsTimer类的实例像工具箱上的其它控件一样你可以让Visual Studio NET处理其生成或者你自己手动的实例和初始化这个类
Figure 定时器控件
在组件页上的定时器控件可以被安全的用在任何类中这个控件创建了一个SystemTimersTimer类的实例如果你正在使用Visual Studio NET工具箱无论是Windows窗体设计器还是组件类设计器你都可以安全的使用这个类在Visual Studio NET中当你设计一个派生于SystemComponentModelComponent的类时使用组件类设计器SystemThreadingTimer类不出现在Visual Studio NET工具箱窗口上它稍微有点复杂但提供了一个更高级别的控件稍后你会在本文章中看到
Figure 例子程序
让我们首先研究SystemWindowsFormsTimer和SystemTimersTimer类这两个类有着非常相似的对象模型稍后我将探索更加高级的SystemThreadingTimer类Figure 是我将在整个文章引用的例子程序的一个屏幕快照这个应用程序将会让你获得对这几个定时器类的清晰的理解你可以从本文章的开始链接处下载完整的代码并试验它
System
Windows
Forms
Timer
如果你在找一个节拍器你已经走错了地方了这个定时器类引发的定时器事件是同你的窗口应用程序的其余代码相同步的这意味着正在执行的代码从来不会被这个定时器类的实例所抢占(假设你不调用ApplicationDoEvents)就像一个典型窗体程序里的其它代码一样任何驻留在一个定时器事件处理函数(指的是该类型的定时器类)中的代码也是使用应用程序的UI线程所执行在空闲时候该UI线程同样要对应用程序的窗体消息队列中的所有消息进行负责这不仅包括由这个定时类引发的消息也包括窗体API消息无论何时你的程序不忙于做其它事情时该UI线程就处理这些消息
在Visual Studio NET之前如果你写过Visual Basic代码你可能知道在一个窗口应用程序里当正在执行一个事件处理函数时让你的UI线程去响应其它窗体消息的唯一方法就是调用ApplicationDoEvents方法就像Visual Basic一样从NET框架中调用ApplicationDoEvents能够产生许多问题ApplicationDoEvents产生了对UI消息泵的控制让你对所有未处理的事件进行处理这能够改变我刚才提到的所期望的执行路径如果为了处理由该定时器类产生的定时器事件而在你的代码中有一个ApplicationDoEvents的调用你的程序流程可能会被打断这会产生不希望的行为并使调试困难
运行例子程序就会使这个定时器类的行为变得清楚单击程序的Start按钮接着单击Sleep按钮最后单击Stop按钮将会产生下面的输出结果
System
Windows
Forms
Timer Started @
:
:
PM
> Timer Event
@
:
:
PM on Thread
UIThread
> Timer EVENT
@
:
:
PM on Thread: UIThread
> Timer Event
@
:
:
PM on Thread: UIThreadSleeping for
ms
> Timer Event
@
:
:
PM on Thread: UIThreadSystem
Windows
Forms
Timer Stopped @
:
:
PM
例子程序设置SystemWindowsFormsTimer类的间隔属性为毫秒正如你所看到的当UI线程正在睡眠(秒)期间如果定时器事件处理函数仍然继续捕捉定时器事件的话当睡眠线程再次被唤醒的时候应该有个定时器事件被显示——在UI线程睡眠时每秒钟一个然而当UI线程在睡眠时定时器却保持挂起状态
[] [] [] []