背景
每种语言都有自己的定时器(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实现的。