這篇部落格將梳理一下.NET中4個Timer類,及其用法。
1. System.Threading.Timer
public Timer(TimerCallback callback, object state, int dueTime, int period);
callback委託將會在period時間間隔內重複執行,state參數可以傳入想在callback委託中處理的對象,dueTime標識多久後callback開始執行,period標識多久執行一次callback。
using System.Threading;// System.Threading.TimerTimer 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中一條新線程中執行的。
2. System.Timers.Timer
System.Timers.Timer和System.Threading.Timer相比,提供了更多的屬性,
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);
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。