.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事件处理而延迟。
本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/536247 ,如需转载请自行联系原作者