计时器

 .net提供4种计时器,2种通用多线程计时器
System.Threading.Timer
System.Timers.Timer

2种专用单线程计时器

System.Windows.Forms.Timer (Windows Forms timer)

System.Windows.Threading.DispatcherTimer (WPF timer)
 
多线程计时器更加精确灵活,单线程计时器更安全和方便,特别是对于简单的任务比如更新窗体控件之类的。
 
 System.Threading.Timer是最简单的多线程计时器:它只有一个构造器和2个方法。看下面的例子。一个计时器5秒后调用Tick方法,然后每秒调用一次,直到用户按回车。
static void Main()
        {
            // First interval = 5000ms; subsequent intervals = 1000ms
            Timer tmr = new Timer(Tick, "tick...", 5000, 1000);
            Console.ReadLine();
            tmr.Dispose(); // This both stops the timer and cleans up.
        }
        static void Tick(object data)
        {
            // This runs on a pooled thread
            Console.WriteLine(data); // Writes "tick..."
        }
你可以改变间隔时间,如果你只想调用一次,只需指定Timeout.Infinite作为构造方法的最后一个参数。
 
.NET Framework提供另一个计时器类。它简单包裹了System.Threading.Timer,并且额外提供一些功能:
是一个控件
Interval属性代替了Change方法
Elapsed事件代替了回调委托
Enabled属性来启动和停止计时器
Start和Stop方法,如果你被Enabled属性混淆了的话
AutoReset标志表示一个循环事件
一个SynchronizingObject属性带有Invoke和BeginInvoke方法,用来安全的调用WPF元素和Windows Form控件。
看下面的例子。
using System;
    using System.Timers; // Timers namespace rather than Threading
    class Program
    {
        static void Main()
        {
            Timer tmr = new Timer(); // Doesn't require any args
            tmr.Interval = 500;
            tmr.Elapsed += tmr_Elapsed; // Uses an event instead of a delegate
            tmr.Start(); // Start the timer
            Console.ReadLine();
            tmr.Stop(); // Stop the timer
            Console.ReadLine();
            tmr.Start(); // Restart the timer
            Console.ReadLine();
            tmr.Dispose();
        }
        static void tmr_Elapsed(object sender, EventArgs e)
        {
            Console.WriteLine("Tick");
        }
    }

多线程计时器使用的是线程池,这意味着回调方法或者Tick事件可能每次由不同的线程调用,此外,每次都很准时,不管先前一次Tick是否已经执行完成。因此回调或者事件必须是线程安全的。

多线程timer的精确性依靠于操作系统,通常有10-20ms的误差。如果想要更高级别的精确性,你就需要用本地interop,并且调用Windows multimedia timer。这个的精确性在1ms之内,它定义在winmm.dll中。

NET Framework 提供了计时器来为WPF和Winform消除线程安全问题。

• System.Windows.Threading.DispatcherTimer (WPF)

• System.Windows.Forms.Timer (Windows Forms)

单线程Timer应该在他们各自的环境中运行,如果你使用Winform计时器在Windows  Service Application,Timer事件不会被触发。

这些类暴露出来的方法和System.Timers.Timer的用法相似,但是不同在于内部的执行原理。不是使用线程池产生计时器事件,WPF和WinForm计时器依靠消息泵机制来作为他们的接口模型。这意味着Tick事件总是触发在初始创造这个计时器的线程上,在通常的应用程序中,也是同一个线程管理用户接口元素和控件的。这样设计有很多好处:

不需要在担心线程安全

前一个Tick不完成,后一个Tick不开始。

可以在Tick事件中直接更新用户控件,而不需要Control.Invoke或者Dispatcher.Invoke。

听起来都不错,但是程序使用此类计时器不是真正的多线程,没有并行执行,一个线程服务于所以的计时器,包括UI事件。这就有缺点,除非Tick事件处理的很快,不然的话用户界面可能无响应。

这些控件适合在WPF和WinForm中的小工作,比如更新用户界面方面,类似时钟,倒计时等。不然,你还是需要一个多线程计时器,在精确性方面,单线程Timer和多线程Timer类似,10ms左右,尽管单线程Timer稍微不如多线程Timer精确,这是因为它们可能由于用户界面请求或者Timer事件处理而延迟。

 

 

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页