日期:2008-03-02  浏览次数:20564 次

Aiyiweb.Com提示:不论在客户端使用程序还是服务器组件(包括窗口服务)定时器通常扮演一个重要的角色。写一个高效的定时器驱动型可管理代码要求对程序流程有一个清晰的理解及掌握.NET线程模型的精妙之处。.NET框架类库提供了三种不同的定时器类:System.Windows.Forms.Timer, System.Timer

不论在客户端使用程序还是服务器组件(包括窗口服务)定时器通常扮演一个重要的角色。写一个高效的定时器驱动型可管理代码要求对程序流程有一个清晰的理解及掌握.NET线程模型的精妙之处。.NET框架类库提供了三种不同的定时器类:System.Windows.Forms.Timer, System.Timers.Timer, 和System.Threading.Timer。每个类为不同的场合进行设计和优化。本文章将研讨这三个类并让你理解如何及何时应该使用哪一个类。

 

Microsoft Windows里的定时器对象当行为发生时允许你进行控制。定时器一些最常用的地方就是有规律的定时启动一个进程,在事件之间设置间隔,及当进行 图形任务时维护固定的动画速度(而不管处理函数的速度)。在过去,对于使用Visual Basic的开发者来说,定时器甚至用来模仿多任务。

 

正如你所期望的那样,对于你需求应对的不同场合微软为你配备了一些工具。在.NET框架类库中有三种不同的定时器类:System.Windows.Forms.Timer,System.Timers.Timer,和System.Threading.Timer。头两个类出如今Visual Studio .NET的工具箱窗口,这两个定时器控件都允许你直接把它们拖拽到Windows窗体设计器或组件类设计器上。如果你不小心,这就是麻烦的开始。

 

Visual Studio .NET工具箱上的Windows窗体页和组件页(见Figure 1)都有定时器控件。非常容易的错误地使用它们当中的一个,或者更蹩脚的是,基本认识不到它们的不同。仅当目标是Windows窗体设计器时才使用Windows窗体页上的定时器控件。这个控件将在你的窗体上放置一个Systems.Windows.Forms.Timer类的实例。像工具箱上的其它控件一样,你可以让Visual Studio .NET处理其生成或者你本人手动的实例和初始化这个类。

 

Figure 1 定时器控件

 

在组件页上的定时器控件可以被安全的用在任何类中。这个控件创建了一个System.Timers.Timer类的实例。如果你正在使用Visual Studio .NET工具箱,无论是Windows窗体设计器还是组件类设计器你都可以安全的使用这个类。在Visual Studio .NET中当你设计一个派生于System.ComponentModel.Component的类时使用组件类设计器。System.Threading.Timer类不出如今Visual Studio .NET工具箱窗口上。它稍微有点复杂但提供了一个更高级别的控件,稍后你会在本文章中看到。

 

Figure 2 例子程序

 

让我们首先研讨System.Windows.Forms.Timer和System.Timers.Timer类。这两个类有着非常类似的对象模型。稍后我将探索愈加高级的System.Threading.Timer类。Figure 2 是我将在整个文章援用的例子程序的一个屏幕快照。这个使用程序将会让你获得对这几个定时器类的清晰的理解。你可以从本文章的开始链接处下载完整的代码并试验它。

 

System.Windows.Forms.Timer

 

如果你在找一个节拍器,你曾经走错了地方了。这个定时器类引发的定时器事件是同你的窗口使用程序的其余代码相反步的。这意味着正在执行的代码从来不会被这个定时器类的实例所抢占(假设你不调用Application.DoEvents)。就像一个典型窗体程序里的其它代码一样,任何驻留在一个定时器事件处理函数(指的是该类型的定时器类)中的代码也是使用使用程序的UI线程所执行。在空闲时候,该UI线程同样要对使用程序的窗体音讯队列中的所有音讯进行担任。这不只包括由这个定时类引发的音讯,也包括窗体API音讯。无论何时你的程序不忙于做其它事情时该UI线程就处理这些音讯。

 

在Visual Studio .NET之前如果你写过Visual Basic代码,你可能知道在一个窗口使用程序里当正在执行一个事件处理函数时让你的UI线程去呼应其它窗体音讯的独一方法就是调用Application.DoEvents方法。就像Visual Basic一样,从.NET框架中调用Application.DoEvents能够产生许多问题。Application.DoEvents产生了对UI音讯泵的控制,让你对所有未处理的事件进行处理。这能够改变我刚才提到的所期望的执行路径。如果为了处理由该定时器类产生的定时器事件而在你的代码中有一个Application.DoEvents的调用,你的程序流程可能会被打断。这会产生不希望的行为并使调试困难。