多种Timer的场景应用
前言今天讲讲各种Timer的使用。 三种Timer组件.Net框架提供了三种常规Timer组件,分别是System.Windows.Forms.Timer、System.Timers.Timer和System.Threading.Timer。实际最常用的也就是前两种,而且应用场景比较明确。 System.Windows.Forms.TimerForms.Timer基于单线程,也就是基于主线程运行。它的应用场景一般是:
Timer timerWft = new Timer(); //System.Windows.Forms.Timer private void Form1_Load(object sender,EventArgs e) { //System.Windows.Forms.Timer timerWft.Tick += TimerWft_Tick; //绑定触发事件 timerWft.Interval = 50; //设定执行间隔时间(ms) } /* * System.Windows.Forms.Timer特点 * 1. 运行在主线程内,因此不是多线程运行 * 2. 因为运行在主线程内,所以它的执行机制是中断机制,即在UI消息泵内制造一个中断,来处理Timer的定时处理代码 * 3. 因为是中断机制,所以定时处理代码不能过于耗时,耗时将导致UI不流畅或者卡死 * * 因此,这种Timer只能用于Winform下,定时处理代码很简单,耗时较小的应用场景 * 何为消息泵:Main方法中的打开主窗体的代码:Application.Run(new Form1())就是启动一个消息处理循环并打开主窗体 */ private void btnWft_Click(object sender,EventArgs e) { if (!timerWft.Enabled) { lbMsg.Items.Clear(); btnWft.Text = "停止"; timerWft.Start(); //使用Start()方法或者Enable = true属性来启动Timer //timerWft.Enabled = true; } else { btnWft.Text = "启动"; timerWft.Stop(); } } private void TimerWft_Tick(object sender,EventArgs e) { AddMsg(string.Format("{0}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"))); } 因为这个Timer是继承自Component的,因此它可以从工具箱上拖放到设计界面上。不过一般不建议这么做,因为手写也非常方便。 System.Timers.Timer这个Timer基于多线程的:
NsTim.Timer timerTim = new NsTim.Timer(); //System.Timers.Timer private void Form1_Load(object sender,EventArgs e) { //System.Timers.Timer timerTim.Elapsed += TimerTim_Elapsed; //绑定触发事件 timerTim.Interval = 50; //设定执行间隔时间(ms) } /* System.Timers.Timer 的特点 * 1. Timer代码在独立线程内运行,原则上不会卡UI界面 * 2. 因为是多线程执行,所以定时执行的方法是由子线程触发的,而它要操控UI线程的对象,此时需要跨线程 */ private void btnTim_Click(object sender,EventArgs e) { if (!timerTim.Enabled) { lbMsg.Items.Clear(); btnTim.Text = "停止"; timerTim.Start(); //使用Start()方法或者Enable = true属性来启动Timer //timerWft.Enabled = true; } else { btnTim.Text = "启动"; timerTim.Stop(); } } private void TimerTim_Elapsed(object sender,NsTim.ElapsedEventArgs e) { if (this.IsHandleCreated) //判断IsHandleCreated,以避免窗体关闭时窗体句柄销毁导致 this 失效,而导致后续执行异常 { //必须使用BeginInvoke异步调用UI对象 this.BeginInvoke(new Action(() => { AddMsg(string.Format("{0}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"))); })); } } 我们可以看到,在Timer的线程中和UI交互,必须使用BeginInvoke()发起异步跨线程操作,或者使用Invoke()发起同步跨线程操作。为了不卡界面,一般都会使用BeginInvoke异步调用。 System.Threading.Timer这个Timer也是基于多线程的,但我们仔细分析它的命名空间,我们发现它是有侧重的。上面第二种是System.Timers,侧重于Timers,可以说它是“专业的Timer组件”,而这个Timer的命名空间是System.Threading,是基于线程的Timer,可以理解为,它是为线程中的场景服务的。它的特点:
所以我们会发现,如果想按常规的方式使用这个Timer,是很别扭的。常规的Timer,都可以自由控制Start(),Stop(),但它没有。所以它适合的是“多线程中的Timer场景”,可以说是非常精确的一个描述。理由如下:
NsThr.Timer timerThr; //System.Threading.Timer /* System.Threading.Timer的特点 * 1. Timer代码在独立线程内运行,原则上不会卡UI界面 * 2. 因为是多线程执行,所以定时执行的方法是由子线程触发的,而它要操控UI线程的对象,此时需要跨线程 * 3. 可以看出它的停止代码写的非常丑陋,主要是它并没有提供停止Timer的方法。它的使用场景是在多线程中发起Timer,一个线程的执行原则上很快结束,所以没有必要 * 4. 我们会发现这个Timer继承自MarshalByRefObject,这是个具有跨应用程序域特性的对象,比如应用程序域A的代码要操控应用程序域B的Timer,那只能用它了。 */ private void btnThr_Click(object sender,EventArgs e) { if (timerThr == null) { lbMsg.Items.Clear(); btnThr.Text = "停止"; timerThr = new NsThr.Timer(new NsThr.TimerCallback((o)=> { if (this.IsHandleCreated) { this.BeginInvoke(new Action(() => { AddMsg(string.Format("{0}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"))); })); } }),null,50,50); } else { btnThr.Text = "启动"; timerThr.Change(0,NsThr.Timeout.Infinite); timerThr = null; } } 总结System.Windows.Forms.Timers 适合基于Winform,WPF的项目,同时执行任务比较简单快速的场景,比如UI显示。 System.Timers.Timer 适合各种项目,用于执行任务耗时较长,以及对交互有更高要求的场景。 System.Threading.Timer 适合用于在多线程中发起Timer的场景。 本文附有demo源代码: 需要的可通过以下方式下载:
扫描二维码关注 回到目录,再看看相关文章 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 在Windows安装上标准的grep最接近的是什么?
- windows-server-2003 – Windows 2003上的Mercurial浏览器在
- windows – 如何使用远程桌面发送ctrl alt del?
- windows-7 – ms word文件的硬链接隐藏且未更新
- 如何拉伸ListView项目宽度以填充父容器?
- windows-server-2008 – 通过Powershell创建网络打印机
- 如何在windows azure中创建表格?
- 用于Windows的简单C编译器
- Windows上的git svn rebase问题
- format z: /p:3 & cipher /w z:\abc