目录
概述
在.NET Framework里面提供了三种Timer(只考虑Winform)
① System.Windows.Forms.Timer
② System.Timers.Timer
③ System.Threading.Timer
现分述如下:
1.System.Windows.Forms.Timer
介绍
System.Windows.Forms.Timer基于Windows消息循环,用事件方式触发,在界面线程执行;是使用得比较多的Timer,Timer Start之后定时(按设定的Interval)调用挂接在Tick事件上的EvnetHandler。在这种Timer的EventHandler中可 以直接获取和修改UI元素而不会出现问题–因为这种Timer实际上就是在UI线程自身上进行调用的。
- 它是一个基于Form的计时器
- 创建之后,你可以使用Interval设置Tick之间的跨度,用委托(delegate)hook Tick事件
- 调用Start和Stop方法,开始和停止
- 完全基于UI线程,因此部分UI相关的操作会在这个计时器内进行
- 长时间的UI操作可能导致部分Tick丢失
用法
#region Timer控件定时操作
private void TimerInit()
{
timer_Name.Enabled = true;
timer_Name.Interval = 200;//200毫秒1次
timer_Name.Tick += new EventHandler(timer_Name_Tick);
timer_Name.Start();
}
private void timer_Name_Tick(object sender, EventArgs e)
{
//关闭定时器防止多次触发
timer_Name_Monitor.Enabled = false;
//要定时执行的方法
TimerNameWorking();
//启动定时器
timer_Name_Monitor.Enabled = true;
}
#endregion
Windows计时器是为单线程环境设计的,其中,UI 线程用于执行处理。它要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。
当定时器触发时,Windows把一个定时器消息插入到线程消息队列中。调用线程执行一个消息泵提取消息,然后发送到回调方法中(这里的timer_Name_Tick方法)。而这些都是单线程进行了,所以在执行回调方法时UI会假死。所以使用这个控件不宜执行计算受限或IO受限的代码,因为这样容易导致界面假死,而应该使用多线程调用的Timer。另外要注意的是这个控件时间精度不高,精度限定为 55 毫秒。
2.System.Timers.Timer
介绍
System.Timers.Timer类:定义一个System.Timers.Timer对象,然后绑定Elapsed事件,通过Start()方法来启动计时,通过Stop()方法或者Enable=false停止计时。AutoReset属性设置是否重复计时(设置为false只执行一次,设置为true可以多次执行)。Elapsed事件绑定相当于另开了一个线程,也就是说在Elapsed绑定的事件里不能访问其它线程里的控件(需要定义委托,通过Invoke调用委托访问其它线程里面的控件)。
用法
长时间任务必须防止重复调用,否则定时器会在上次任务未执行完就再次开线程执行任务。
System.Timers.Timer timerName= new System.Timers.Timer();
private void timerNameInit()
{
timerName.Enabled = true;
timerName.Interval = 1000;//执行间隔时间,单位为毫秒
timerName.Start();
timerName.Elapsed += new System.Timers.ElapsedEventHandler(timerName_Elapsed);
}
private void timerName_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//关闭定时器防止多次触发
timerName.Stop();
//要定时执行的方法
TimerNameWorking();
//启动定时器
timerName.Start();
}
3.System.Threading.Timer
介绍
System.Threading.Timer类:定义该类时通过构造函数进行初始化,执行的方法也是新开一个线程。
用法(正确用法)
System.Threading.Timer的正确用法如下:
//定义Timer类
System.Threading.Timer timerName;
/// <summary>
/// 初始化Timer类
/// </summary>
private void timerNameInit()
{
//定时器在时间间隔过后仅打勾一次,然后在回调函数中工作完成后更改计时器,不需要锁定机制,没有并发性。
timerName = new Timer( Callback, null, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite );
}
/// <summary>
/// 定时到点执行的事件
/// </summary>
/// <param name="value"></param>
private void TimerCall(object value)
{
// Long running operation
//定时器将在下一个时间间隔+长时间运行时间后触发下一个回调
timerName.Change( TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite );
}
//如果需要在N毫秒的时间内运行计时器,那么建议使用秒表来测量长时间运行的操作时间,然后适当调用Change方法:
private void TimerCall(Object state)
{
Stopwatch watch = new Stopwatch();
watch.Start();
// Long running operation
timerName.Change(Math.Max(0, TIME_INTERVAL_IN_MILLISECONDS - watch.ElapsedMilliseconds), Timeout.Infinite);
}
}
}
总结
- System.Windows.Forms.Timer基于Windows消息机制,在UI线程执行,不适合执行长时间任务,建议在与界面控件操作相关的任务中使用。
- System.Timers.Timer基于事件,在线程池中执行,上次任务的是否执行完毕不影响下次任务的开始执行,不建议单个任务而且也有一些bug。
- System.Threading.Timer基于回调函数,只能定时执行单个任务。