这篇博客将梳理一下.NET中4个Timer类,及其用法。this
1. System.Threading.Timerspa
public Timer(TimerCallback callback, object state, int dueTime, int period);线程
callback委托将会在period时间间隔内重复执行,state参数能够传入想在callback委托中处理的对象,dueTime标识多久后callback开始执行,period标识多久执行一次callback。code
using System.Threading; // System.Threading.Timer Timer timer = new Timer(delegate { Console.WriteLine($"Timer Thread: {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine($"Is Thread Pool: {Thread.CurrentThread.IsThreadPoolThread}"); Console.WriteLine("Timer Action."); }, null, 2000, 1000 ); Console.WriteLine("Main Action."); Console.WriteLine($"Main Thread: {Thread.CurrentThread.ManagedThreadId}"); Console.ReadLine();
Timer回掉方法执行是在另外ThreadPool中一条新线程中执行的。orm
2. System.Timers.Timer对象
System.Timers.Timer和System.Threading.Timer相比,提供了更多的属性,blog
Interval 指定执行Elapsed事件的时间间隔;队列
Elapsed 指定按期执行的事件;事件
Enabled 用于Start/Stop Timer;博客
Start 开启Timer
Stop 中止Timer
System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 500; timer.Elapsed += delegate { Console.WriteLine($"Timer Thread: {Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine($"Is Thread Pool: {Thread.CurrentThread.IsThreadPoolThread}"); Console.WriteLine("Timer Action"); timer.Stop(); }; timer.Start(); Console.WriteLine("Main Action."); Console.WriteLine($"Main Thread: {Thread.CurrentThread.ManagedThreadId}"); Console.ReadLine();
Timer Elapsed按期任务是在ThreadPool的线程中执行的。
3. System.Windows.Forms.Timer
Interval 指定执行Elapsed事件的时间间隔;
Tick 指定按期执行的事件;
Enabled 用于Start/Stop Timer;
Start 开启Timer
Stop 中止Timer
使用System.Windows.Forms.Timer来更新窗体中Label内时间,
using System.Windows.Forms; public Form1() { InitializeComponent(); this.Load += delegate { Timer timer = new Timer(); timer.Interval = 500; timer.Tick += delegate { System.Diagnostics.Debug.WriteLine($"Timer Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}"); System.Diagnostics.Debug.WriteLine($"Is Thread Pool: {System.Threading.Thread.CurrentThread.IsThreadPoolThread}"); this.lblTimer.Text = DateTime.Now.ToLongTimeString(); }; timer.Start(); System.Diagnostics.Debug.WriteLine($"Main Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}"); }; }
Timer Tick事件中执行的事件线程与主窗体的线程是同一个,并无建立新线程(或者使用ThreadPool中线程)来更新UI。下面将代码作一个改动,使用System.Timers.Timer来更新UI上的时间,代码以下,
public Form1() { InitializeComponent(); this.Load += delegate { System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 500; timer.Elapsed += delegate { System.Diagnostics.Debug.WriteLine($"Timer Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}"); System.Diagnostics.Debug.WriteLine($"Is Thread Pool: {System.Threading.Thread.CurrentThread.IsThreadPoolThread}"); this.lblTimer.Text = DateTime.Now.ToLongTimeString(); }; timer.Start(); System.Diagnostics.Debug.WriteLine($"Main Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}"); }; }
很熟悉的一个错误。由于Label是由UI线程建立的,因此对其进行修改须要在UI线程中进行。System.Timers.Timer中Elasped执行是在ThreadPool中新建立的线程中执行的。因此会有上面的错误。
4. System.Windows.Threading.DispatcherTimer
属性和方法与System.Windows.Forms.Timer相似。
using System.Windows.Threading; public MainWindow() { InitializeComponent(); this.Loaded += delegate { //DispatcherTimer DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Start(); Debug.WriteLine($"Main Thread Id: {Thread.CurrentThread.ManagedThreadId}"); timer.Tick += delegate { tbTime.Text = DateTime.Now.ToLongTimeString(); Debug.WriteLine($"Timer Thread Id: {Thread.CurrentThread.ManagedThreadId}"); timer.Stop(); }; }; }
DispatcherTimer中Tick事件执行是在主线程中进行的。
使用DispatcherTimer时有一点须要注意,由于DispatcherTimer的Tick事件是排在Dispatcher队列中的,当系统在高负荷时,不能保证在Interval时间段执行,可能会有轻微的延迟,可是绝对能够保证Tick的执行不会早于Interval设置的时间。若是对Tick执行时间准确性高能够设置DispatcherTimer的priority。例如:
DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Send);
感谢您的阅读。