System.Windows.Forms.Timer System.Windows.Threading.DispatcherTimer System.Web.UI.Timer通常情况下,WinForm、WPF中的定时器是在UI线程上执行回调函数,因此可以直接访问UI元素。由于WinForm、WPF支持单线程单元模型(Single-Thread Apartment,STA),定时器间隔事件是在UI线程上触发,因此,不用担心线程安全问题。System.Web.UI.Timer是通过Javascript定时器和服务端异步回调实现,也是单线程的。
public partial class TimerFrom : Form { private System.Windows.Forms.Timer digitalClock; private void TimerFrom_Load(object sender, EventArgs e) { digitalClock = new System.Windows.Forms.Timer();//创建定时器 digitalClock.Tick += new EventHandler(HandleTime);//注册定时任务事件 digitalClock.Interval = 1000;//设置时间间隔 digitalClock.Enabled = true; // 堆代码 duidaima.com digitalClock.Start(); //开启定时器 } public void HandleTime(Object myObject, EventArgs myEventArgs) { labelClock.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); } private void frmTimerDemo_FormClosed(object sender, FormClosedEventArgs e) { digitalClock.Stop();//停止定时器 digitalClock.Dispose(); } }System.Windows.Threading.DispatcherTimer
private void Dt_Tick(object sender, EventArgs e) { Dispatcher.BeginInvoke((Action)delegate () { text1.Text = DateTime.Now.ToString(); }); Console.WriteLine(DateTime.Now.ToString()); } private void Button_Click(object sender, RoutedEventArgs e) { Task.Run(() =>{ DispatcherTimer dt = new DispatcherTimer(); dt.Tick += Dt_Tick; dt.Interval = TimeSpan.FromSeconds(1); dt.Start(); Dispatcher.Run(); }); }上述代码中,DispatcherTimer是非UI线程中创建,定时任务中访问UI元素text1,需要通过Invoke或者BeginInvoke封送(marshal)到UI线程上运行,而Console.WriteLine则可以直接运行。
System.Threading.PeriodicTimer(.NET 6+)
var stateTimer = new var autoEvent = new AutoResetEvent(false); Timer(CheckStatus, autoEvent, 1000,250); private int invokeCount=0; public void CheckStatus(Object stateInfo) { AutoResetEvent autoEvent = (AutoResetEvent)stateInfo; Console.WriteLine("{0} Checking status {1,2}.",DateTime.Now.ToString("h:mm:ss.fff"),(++invokeCount).ToString()); if(invokeCount == 10) { invokeCount = 0; autoEvent.Set(); } }System.Timers.Timer
public partial class TimerFrom : Form { private System.Timers.Timer timer; private void TimerFrom_Load(object sender, EventArgs e) { // 支持注册多个处理程序 timer.Elapsed += (sender, e) => { label1.Text = DateTime.Now.ToLongTimeString(); }; timer.Elapsed += (sender, e) => { Console.WriteLine(DateTime.Now.ToLongTimeString()); }; //自定义回调执行的方式(指定对象所在的线程),SynchronizingObject=null时在线程池上执行 timer.SynchronizingObject = this; timer.AutoReset = true; timer.Start(); } }本例中将SynchronizingObject属性设置为Form对象,因此Elapsed的处理程序在UI线程上执行,可以直接修改label1.Text,如果SynchronizingObject属性为null,处理程序则是在线程池线程上执行,修改label1.Text时需要通过Invoke或者BeginInvoke封送(marshal)到UI线程上运行。
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(15)); using (var timer = new PeriodicTimer(TimeSpan.FromSeconds(1))) { try { while (await timer.WaitForNextTickAsync(cts.Token)) { await Task.Delay(3000); Console.WriteLine($"ThreadId is {Thread.CurrentThread.ManagedThreadId} --- Time is {DateTime.Now:HH:mm:ss}"); } } catch (OperationCanceledException) { Console.WriteLine("Operation cancelled"); } }小结