浅谈.NET 中的定时器及使用方法

发布于: 2018-10-17    浏览: 1564    作者:Wu

定时器是系统常用的组件之一,程序员可以根据自己的需求定制一个定时器类型,也可以使用.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,             //第一次执行调用方法等待时间 // 指定零 (0) 可立即启动计时器。
                                  //指定零 (-1) 表示本定时器被禁用。
                                 //Change(Int32,Int32)方法可以改写定时器参数 
 int period               // 执行间隔时间          
                              //如果 period 为零 (0) 或 -1 毫秒,而且dueTime 为正,则只会调用一次方法; 
                            //然后计时器的定时行为将被禁用,使用 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(Say), null, 0, 1000);
    //1S定时器  
    } 
    //函数形式参数必须是object格式 
    public void Say(object a )      
      {       
       Console.WriteLine("你好");       
     }


 

    

    using System; 
    using System.Threading; 
    class TimerExample   
     { 
        static void Main() 
          { 
        //创建一个事件来指示超时计数阈值 //定时器回调。 
        AutoResetEvent autoEvent = new AutoResetEvent(false); 
        StatusChecker  statusChecker = new StatusChecker(10); 
        // 创建一个推断的委托,调用计时器的方法。 
        TimerCallback tcb = statusChecker.CheckStatus; 
        // 创建一个指示委托调用的计时器。 
        Console.WriteLine("{0} Creating timer.\n",DateTime.Now.ToString("h:mm:ss.fff")); 
        Timer stateTimer = new Timer(tcb, autoEvent, 1000, 250); 
        // 当自动事件信号,改变周期到每一个  
        autoEvent.WaitOne(5000, false);     
        stateTimer.Change(0, 500); 
        Console.WriteLine("\nChanging period.\n"); 
        //当autoevent信号的第二次,处置  
        autoEvent.WaitOne(5000, false); 
        stateTimer.Dispose(); 
     Console.WriteLine("\nDestroying timer.");      
          }   
     } 
        class StatusChecker           
     { 
        private int invokeCount; private int maxCount; public StatusChecker(int count)            
        {                
            invokeCount = 0;                
            maxCount = count;           
         } 
            // 此方法由定时器委托调用。 
        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 == maxCount)          
             { 
                    // 重置计数器和信号主信号。
                     invokeCount  = 0; 
                    autoEvent.Set(); 
             } 
        }
    }


 

 

 

 

三、 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秒提前终结!!!");        
     }


 ——本文并非原创,如有侵权请联系管理员删除。

在线客服

售前咨询

售后服务

投诉/建议

服务热线
0731-83091505
18874148081