C#.NET 中的定时器及使用方法
定时器是系统常用的组件之一,程序员可以根据自己的需求定制一个定时器类型,也可以使用.net内建的定时器类型。在.net中一共为程序员提供了3种定时器:
- system.windows.forms.timer类型
- system.threading.timer类型
- system.timers.timer类型
一、system.windows.forms.timer
从这个定时器的命名空间可以看出,.net设计这个定时器的目的是为了方便程序员在window form中使用的定时器。当一个system.windows.forms.timer类被构造时,当前定时器会和当前线程进行关联。而当计时器的计满后,一个定时器消息将被插入到当前线程的消息队列中。当前线程逐一处理消息中的所有消息,并一一派发给各自的处理方法。这样的机制和利用工作者进程定时有很大的区别,
system.windows.forms.timer类型并没有涉及多线程的操作,定时器的设置、定时方法的执行都在同一个线程之上。这就意味着system.windows.forms.timer并不能准确计时,尤其当消息阻塞时,定时器的误差将会更大,因为定时器消息只能等待在前面的所有消息处理完后才能得到处理。但是因为system.windows.forms.timer类型的定时器并不涉及多线程的操作,因此是线程安全的,不会发生回调方法重入的问题。
主要使用步骤如下:
1. system.windows.forms.timer mytimer = new system.windows.forms.timer();//实例化
2. mytimer.tick += new eventhandler(函数名); //给timer挂起事件
3. mytimer.enabled = true;//使timer可用
4. mytimer.interval = n; //设置时间间隔,以毫秒为单位
5. mytimer.stop(); //如果要暂停计时则使用stop()方法
6. mytimer.enabled = false;//若要停止使用timer,则使之不可用
system.windows.forms.timer例程:
using system.windows.forms; namespace windowsformsapplication1 { public partial class form1 : form { public form1() { initializecomponent(); } //实例化一个timer system.windows.forms.timer mytimer = new system.windows.forms.timer(); private void starttimebtn_click(object sender, eventargs e)//开始计时 { //给timer挂起事件 mytimer.tick += new eventhandler(callback); //使timer可用 mytimer.enabled = true; //设置时间间隔,以毫秒为单位 mytimer.interval = 1000;//1s } private void stoptimebtn_click(object sender, eventargs e)//停止计时 { //计时开始 mytimer.stop(); } //回调函数 private void callback(object sender, eventargs e) { //获取系统时间 20:16:16 textbox1.text = datetime.now.tolongtimestring().tostring(); } } }
二、system.threading.timer
这个定时器类的使用相对复杂,但同时它也是最优化的一个定时器类型。system.threading.timer的定时方法在独立的线程上执行,定时时间更为准确。所有的对象有一个线程控制,当下一个定时到达时,该线程会负责在线程中获得一个新的工作者线程,用以执行相应的回调方法。
虽然这个定时器是相对最优化的一个定时器类型,但是从其机制上来讲,其并不是线程安全的,可能会出现回调方法重入的问题。解释下方法重入,是一个有关多线程编程的概念,意思大概是:同一程序中,多个线程同时运行时,就可能发生同一个方法被多个进程同时调用的情况。当这个方法中存在一些非线程安全的代码时,方法重入会导致数据发生同步错误的bug。
主要使用步骤如下:
1、实例构造一个线程定时器。
system.threading.timer mytimer =
new system.threading.timer(new system.threading.timercallback(timercall), null, 0, 1000);
★timer构造函数资料:
public timer( timercallback callback, // timercallback 委托,表示要执行的方法。 object state, //一个包含回调方法要使用的信息的对象,或者为 null。 int duetime, //调用 callback 之前延迟的时间量(以毫秒为单位)。 //指定 timeout.infinite 可防止启动计时器。 // 指定零 (0) 可立即启动计时器。 //指定零 (-1) 表示本定时器被禁用。 //change(int32,int32)方法可以改写定时器参数 int period //如果 period 为零 (0) 或 -1 毫秒,而且duetime 为正 //则只会调用一次 callback; //然后计时器的定时行为将被禁用,使用 change 可以改写定时器参数。 )
2、编写timercall回调函数
格式:private void timercall(object xxxxx) { .......; .......;}
3、使用change(int32,int32)方法来修改定时器参数实现停止、重新开始等。
4、使用dispose()方法释放定时器资源。
system.threading.timer例程:
public starttimer() { //定义一个对象 system.threading.timer timer = new system.threading.timer( new system.threading.timercallback(mytimer), null, 0, 1000);//1s定时器 } //函数形式参数必须是object格式 public void say(object a ) { console.writeline("你好"); }
三、 system.timers.timer类
这是一个相对较旧的类型,它和system.threading.timer一样,可以由工作者线程来执行回调方法,但同时它也可以在ide环境中被拖到窗体控件上,这个时候它的行为非常类似于system.windows.forms.timer类型,在消息过多时其定时并不准确。 system.timers.timer可以视为system.threading.timer的一个包装,其类型设计相对古老,不建议使用该定时器。
主要使用步骤如下:
1. system.timers.timer mytimer = new system.timers.timer( 1000 ); //实例化 设置时间间隔
2. mytimer .elapsed += new system.timers.elapsedeventhandler(函数名); //给timer挂起事件
3. mytimer .autoreset = true; //设置是执行一次(false)还是一直执行(true);
4. mytimer .enabled = true; //是否执行system.timers.timer.elapsed事件;
system.timers.timer例程代码:
system.timers.timer t = newsystem.timers.timer(5000); //设置时间间隔为5秒 private void form1_load(object sender,eventargs e) { t.elapsed += newsystem.timers.elapsedeventhandler(timer_timesup); t.autoreset = false; //每到指定时间elapsed事件是触发一次(false),还是一直触发(true) } private void btnstart_click(objectsender, eventargs e) { t.enabled = true; //是否触发elapsed事件 t.start(); } private void timer_timesup(objectsender, system.timers.elapsedeventargs e) { //到达指定时间5秒触发该事件输出 helloworld!!!! system.diagnostics.debug.writeline("helloworld!!!!"); } private void btnstop_click(objectsender, eventargs e) { t.stop(); system.diagnostics.debug.writeline("未到指定时间5秒提前终结!!!"); }
参考链接:http://www.cnblogs.com/debuglzq/archive/2012/08/05/2623669.html
https://blog.csdn.net/zhouqt/article/details/51779264
http://www.360doc.com/content/11/0812/11/1039473_139824496.shtml