本文介绍下,C#中的各种定时器Timer,介绍它们之间的区别,通过具体的例子学习其使用方法。有需要的朋友,可以参考下。
在使用Timer类时,要考虑到单线程与多线程的问题,不然会遇到些很莫名的问题,这点要注意。
System.Threading.Timer 是一个简单的轻量计时器,它使用回调方法并由线程池线程提供服务。 在必须更新用户界面的情况下,建议不要使用该计时器,因为它的回调不在用户界面线程上发生。 在此类情况下,System.Windows.Threading.DispatcherTimer 是更好的选择,因为其事件是在用户界面线程上引发的。
1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Timers.Timer类里
System.Windows.Forms.Timer是应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或Delphi中的Timer控件,内部使用API SetTimer实现的。它的主要缺点是计时不精确,而且必须有消息循环,Console Application(控制台应用程序)无法使用。
System.Timers.Timer和System.Threading.Timer非常类似,它们是通过.NET Thread Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求。System.Timers.Timer还可以应用于WinForm,完全取代上面的Timer控件。它们的缺点是不支持直接的拖放,需要手工编码。
按线程归类 多线程计时器
1、System.Threading.Timer 2、System.Timers.Timer
特殊目的的单线程计时器:
1、System.Windows.Forms.Timer(Windows Forms Timer) 2、System.Windows.Threading.DispatcherTimer(WPF timer);
计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用,适用于单线程环境,
在此环境中, UI 线程用于执行处理。它要求用户代码提供 UI 消息泵, 并且始终从同一线程操作, 或将调用封送到
其他线程。Windows 窗体计时器组件是单线程的, 且限制为55毫秒的准确度,准确性不高
多线程计时器比较强大,精确,而且可扩展性强; 单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。 System.Threading.Timer是最简单的多线程计时器。在下面的例子中,定时器在5秒后开始定时1秒的调用Tick方法。
复制代码 代码示例:
publicstaticvoidMain()
{
//5秒后开始运行,接着每隔1秒的调用Tick方法
Timertmr=newTimer(Tick,"tick...",5000,1000);
Console.ReadLine();
tmr.Dispose();
}
staticvoidTick(objectdata)
{
Console.WriteLine(data);
}
.net framework提供的另一个计时器System.Timers.Timer.简单的对System.Threading.Timer进行了包装。增加了下面几个特性。
实现了Component,所以可以在设计器显示。代替Change方法的一个Interval属性代替callback委托的一个Elapsed事件启动和停止timer的Enabled属性,默认是false。为了避免Enabled造成混乱,提供了Start和Stop方法。是否在每次指定的间隔结束时引发Elapsed时间,还是仅间隔第一次结束后运行的AutoReset属性。在WPF或Windows Forms中安全的调用方法的SynchronizingObject对象。
复制代码 代码示例:
public static void MainThread()
{
Timertmr=newTimer();
tmr.Interval=500;
tmr.Elapsed+=newElapsedEventHandler(tmr_Elapsed);
tmr.Start();
Console.ReadLine();
tmr.Stop();
Console.ReadLine();
tmr.Start();
Console.ReadLine();
tmr.Dispose();
}
staticvoidtmr_Elapsed(objectsender,ElapsedEventArgse)
{
Console.WriteLine("Tick...");
}
单线程计时器: 1:System.Windows.Forms.Timer(Windows Forms Timer) 2:System.Windows.Threading.DispatcherTimer(WPF timer); 单线程计时器是被设计成属于他们执行环境的计时器,如果你在一个Windows服务应用程序中使用Windows Forms的Timer,timer 事件并不会被触发,只有在对应的环境下才会被触发。
像System.Timers.Timer一样,他们也提供了相同的成员(Interval,Tick,Start,Stop),但是他们内部的工作原理不同,
WPF和Windows Forms的计时器使用消息循环机制来取代线程池产生消息的机制。
这意味着Tick事件总是在创建timer的那个线程上执行,同时也意味着如果上一个Tick消息还未被处理,即使时间超过了间隔时间,在消息循环中也只存在一个Tick消息。 优点: 忘记线程安全。一个Tick事件在前一个Tick事件被处理完毕前不会被触发。你可以直接在Tick事件处理代码中更新控件,不需要调用Control.Invoke或Dispatcher.Invoke. 看下在Winform中使用单线程定时器的效果:
复制代码 代码示例:
//基于Windows消息循环的单线程计时器
privateSystem.Windows.Forms.Timertimer=newTimer(){};
publicForm1()
{
InitializeComponent();
timer.Tick+=newEventHandler(timer_Tick);
timer.Enabled=true;
}
voidtimer_Tick(objectsender,EventArgse)
{
//模拟的做一些耗时的操作
System.Threading.Thread.Sleep(2000);
}
如果运行上面的代码,会发现UI界面响应速度很慢, 原因:单线程计时器基于Windows消息循环,应用程序会同步的处理计时器的消息。 解决方法: 使用多线程计时器:只要修改代码使用多线程计时器即可:
复制代码 代码示例:
//使用多线程计时器
privateSystem.Timers.Timertimer=newSystem.Timers.Timer();
publicForm1()
{
InitializeComponent();
timer.Elapsed+=newSystem.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled=true;
}
voidtimer_Elapsed(objectsender,System.Timers.ElapsedEventArgse)
{
//模拟的做一些耗时的操作
System.Threading.Thread.Sleep(2000);
}
以上示例,展示了单线程计时器的缺点: 除非Tick事件的处理代码执行的非常快,否则UI界面会变得响应很慢。 所以 WPF和Windows Forms的计时器都非常适合小任务,尤其是界面更新的任务。例如时钟和计数显示。否则,你需要一个多线程计时器。 设为1000,再设一个变量每次加1.加12次后做你要做的事,这样就准了。
建议大家亲处测试下上面的例子,哪个比较好用,就选哪一个吧。