背景
每種語言都有自己的定時器(Timer),很多人熟悉Javascript中的setInterval和setTimeout,在Javascript中為了實現平滑的動畫一般采用setTimeout模擬setInterval,這是因為:setTimeout可以保證兩次定時任務之間的時間間隔,而setInterval不行(小於設置的間隔時間)。C#中如何模擬setTimeout呢?
System.Timers.Timer
模擬setInterval
代碼
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Timers; 7 using System.Threading; 8 9 namespace TimerTest 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 var timer = new System.Timers.Timer(2000); 16 timer.Elapsed += timer_Elapsed; 17 18 Console.WriteLine(DateTime.Now.Second); 19 timer.Start(); 20 21 Console.Read(); 22 } 23 24 static void timer_Elapsed(object sender, ElapsedEventArgs e) 25 { 26 Thread.Sleep(6000); 27 Console.WriteLine(DateTime.Now.Second); 28 } 29 } 30 }
運行效果
分析
如果定時器任務執行的時間比較長,兩次任務之間會有重疊,下面介紹如何避免這個問題。
模擬setTimeout
代碼
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Timers; 7 using System.Threading; 8 9 namespace TimerTest 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 var timer = new System.Timers.Timer(2000); 16 timer.Elapsed += timer_Elapsed; 17 timer.AutoReset = false; 18 19 Console.WriteLine(DateTime.Now.Second); 20 timer.Start(); 21 22 Console.Read(); 23 } 24 25 static void timer_Elapsed(object sender, ElapsedEventArgs e) 26 { 27 Thread.Sleep(6000); 28 Console.WriteLine(DateTime.Now.Second); 29 30 (sender as System.Timers.Timer).Start(); 31 } 32 } 33 }
運行效果
分析
這樣就能保證定時任務的執行不會重疊了。
備注
while(true) + sleep 也可以做到,不知道微軟的Timer內部是不是用sleep實現的。