在开发中经常用到Timer,也注意到了有多个Timer且每个都能实现自己想要的简单功能,却从未思考过它们的异同。前些日子在开发的时候用到了Timer,由于对Timer的时间要求比较严格,结果发现了很多问题。最后才意识到原来自己对各个Timer很是不了解。认真研究一下它们的异同势在必行。MSDN magazine上有一篇很不错的文章(http://msdn.microsoft.com/en-us/magazine/cc164015.aspx)介绍了3个Timer的异同,很不错。本文只是对该文章学习的笔记,因此如果你是为了详细了解Timers之间的异同可以直接看MSDN的文章,不必阅读以下内容。当然你也许想快速看一下要点,或许可以浏览一下我的笔记。
要点一:
- 在.Net类库中有3个Timer, 分别是:System.Windows.Forms.Timer; System.Timers.Timer 和System.Threading.Timer。 3个中只有System.Timers.Timer是线程安全的。
要点二:
- System.Windows.Forms.Timer的事件是和Form的其它代码在一个线程的(UI Thread)。因此,Form的其它代码会影响Timer,比如Form内Thread.Sleep()会导致Timer的等待。
- 虽然可以把System.Windows.Forms.Timer的Interval设成最小为1的值,但是.Net Framework介绍此Timer只能准确模拟大于55毫秒的时间间隔。
要点三:
- System.Timers.Timer是设计成多线程环境应用,是线程安全的。
- System.Timers.Timer通过一个工作线程来调用事件函数。这就要求事件处理函数遵循一个Win32开发的金牌规则——永远不要在非创建控件的线程内访问该控件。
- System.Timers.Timer有个SynchronizingObject 属性,把该属性设成要访问的控件,可以使时间处理函数运行在创建该控件的线程内。
- 如果使用Visual Studio 的toolbox来使用System.Timers.Timer控件,Visual Studio将会自动设置SynchronizingObject 属性。因此,其表面上与System.Windows.Forms.Timer看起来没什么区别。实际上它们的区别很大:
- 对System.Windows.Forms.Timer而言,当UI Thread没来得及处理完其当前的事件处理函数时,此Timer是不会继续触发下一个事件处理函数的,即使间隔时间到达。而System.Timers.Timer则不同,其事件处理函数会严格按照时间间隔逐个触发。假若前面的事件函数没完成,Timer会自动把后面的处理函数加入队列,等待前面的执行完毕来后接着执行。
- 由于System.Timers.Timer是线程安全的,因此其它线程可以调用其Stop方法。这就可能造成Stop方法在另一个线程的Elapsed事件发生前。解决这个问题的办法是:事件的处理函数的参数ElapsedEventArgs内含一个SignalTime属性来标识事件的时间,然后对比该事件与Stop()函数调用的时间来确定时间的先后。
- System.Timers.Timer的AutoReset属性可用来设置该timer是持续执行还是只执行一次。
- System.Timers.Timer开始之后其Interval属性仍可以修改,但是修改后计数器会归零。比如当前的Interval为5秒,3秒后修改Interval为10,那么下一次事件的触发时间距上次触发时间是13秒。
下一篇将介绍System.Threading.Timer的学习备忘。。。