1. 程式人生 > >C#.NET定時器類及使用方法

C#.NET定時器類及使用方法

C#.NET 定時器類及使用方法

       在.net常用的定時器類有下面三種,使用定時器時需要設定引數,如間斷時間、定時器計溢位後的回撥函式、延時、開始等,定時器的的主要方法有開始、終止等,不同的定時器實現上述的方法會有一些差異,本文會針對具體的定時器一一舉例說明。

 
  • 1、System.Windows.Forms.Timer類
  • 2、System.Threading.Timer類
  • 3、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例程:

 

[csharp]

view plain copy

print?

  1. using System.Windows.Forms;  
  2.   
  3. namespace WindowsFormsApplication1  
  4. {  
  5.     public partial class Form1 : Form  
  6.     {  
  7.         public Form1()  
  8.         {  
  9.             InitializeComponent();  
  10.         }  
  11.         //例項化一個timer  
  12.         System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();  
  13.           
  14.     private void StartTimeBtn_Click(object sender, EventArgs e)//開始計時  
  15.         {   
  16.             //給timer掛起事件  
  17.             myTimer.Tick  += new EventHandler(Callback);  
  18.             //使timer可用  
  19.             myTimer.Enabled = true;  
  20.             //設定時間間隔,以毫秒為單位  
  21.             myTimer.Interval = 1000;//1s  
  22.         }  
  23.         private void StopTimeBtn_Click(object sender, EventArgs e)//停止計時  
  24.         {  
  25.             //計時開始  
  26.             myTimer.Stop();  
  27.         }  
  28.         //回撥函式  
  29.         private void Callback(object sender, EventArgs e)  
  30.         {   
  31.             //獲取系統時間 20:16:16  
  32.             textBox1.Text = DateTime.Now.ToLongTimeString().ToString();  
  33.         }  
  34.     }  
  35. }  
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建構函式資料:

 

[csharp] view plain copy print ?
  1. public Timer(  
  2.     TimerCallback callback,   // TimerCallback 委託,表示要執行的方法。  
  3.     object state,         //一個包含回撥方法要使用的資訊的物件,或者為 null。  
  4.     int dueTime,    //呼叫 callback 之前延遲的時間量(以毫秒為單位)。  
  5.                     //指定 Timeout.Infinite 可防止啟動計時器。  
  6.                     // 指定零 (0) 可立即啟動計時器。  
  7.                     //指定零 (-1) 表示本定時器被禁用。  
  8.                     //Change(Int32,Int32)方法可以改寫定時器引數  
  9.     int period  //如果 period 為零 (0) 或 -1 毫秒,而且dueTime 為正  
  10.                 //則只會呼叫一次 callback;  
  11.                 //然後計時器的定時行為將被禁用,使用 Change 可以改寫定時器引數。  
  12. )  
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 可以改寫定時器引數。
)

 

         https://msdn.microsoft.com/zh-cn/library/system.threading.timer(v=vs.110).aspx

2、編寫timerCall回撥函式

     格式:private  void  timerCall(object   xxxxx)  { …….; …….;}

3、使用Change(Int32,Int32)方法來修改定時器引數實現停止、重新開始等。

4、使用Dispose()方法釋放定時器資源。

 

 

System.Threading.Timer例程:

 

 

[csharp] view plain copy

print?

  1. public startTimer()  
  2. {  
  3.   //定義一個物件  
  4.   System.Threading.Timer timer = new System.Threading.Timer(  
  5.     new System.Threading.TimerCallback(mytimer), null,  
  6.     0, 1000);//1S定時器  
  7. }  
  8.   
  9. //函式形式引數必須是object格式  
  10. public void mytimer(object a )  
  11. {  
  12.   Console.WriteLine(”你好”);  
  13. }  
    public startTimer() 

    { 

      //定義一個物件 

      System.Threading.Timer timer = new System.Threading.Timer( 

        new System.Threading.TimerCallback(mytimer), null, 

        0, 1000);//1S定時器 

    }

 

//函式形式引數必須是object格式
public void mytimer(object a )
{
  Console.WriteLine("你好");
}</pre>

 

 

三、 System.Timers.Timer類

  這是一個相對較舊的型別,它和System.Threading.Timer一樣,可以由工作者執行緒來執行回撥方法,但同時它也可以在IDE環境中被拖到窗體控制元件上,這個時候它的行為非常類似於System.Windows.Forms.Timer型別,在訊息過多時其定時並不準確。  System.Timers.Timer可以視為System.Threading.Timer的一個包裝,其型別設計相對古老,不建議使用該定時器。

System.Timers.Timer例程程式碼:

 

 

[csharp] view plain copy

print?

  1. System.Timers.Timer t = newSystem.Timers.Timer(5000); //設定時間間隔為5秒  
  2. private void Form1_Load(object sender,EventArgs e)  
  3. {  
  4.     t.Elapsed += newSystem.Timers.ElapsedEventHandler(Timer_TimesUp);  
  5.     t.AutoReset = false; //每到指定時間Elapsed事件是觸發一次(false),還是一直觸發(true)  
  6. }  
  7.   
  8. private void btnStart_Click(objectsender, EventArgs e)  
  9. {  
  10.     t.Enabled = true; //是否觸發Elapsed事件  
  11.     t.Start();  
  12. }  
  13. private void Timer_TimesUp(objectsender, System.Timers.ElapsedEventArgs e)  
  14. {  
  15.     //到達指定時間5秒觸發該事件輸出 HelloWorld!!!!  
  16.     System.Diagnostics.Debug.WriteLine(”HelloWorld!!!!”);  
  17. }  
  18. private void btnStop_Click(objectsender, EventArgs e)  
  19. {  
  20.     t.Stop();  
  21.    System.Diagnostics.Debug.WriteLine(”未到指定時間5秒提前終結!!!”);  
  22. }  
        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秒提前終結!!!");
    }</pre>

 

  四、 System.Windows.Threading.DispatcherTimer型別(補充)

  System.Windows.Threading.DispatcherTimer整合到按指定時間間隔和指定優先順序處理的 Dispatcher 佇列中的計時器。因為 DispatcherTimer 操作與其他操作一樣被放置到Dispatcher佇列中,何時執行DispatcherTimer 操作取決於佇列中的其他作業及其優先順序,因此它不能保證會正好在時間間隔發生時執行計時器,但能夠保證不會在時間間隔發生之前執行計時器。如果 System.Timers.Timer 用於 WPF 應用程式,則值得注意的是 System.Timers.Timer 運行於不同於user interface(UI) 執行緒的其他執行緒上。 為了訪問user interface (UI) 執行緒上的物件,需要使用 Invoke 或 BeginInvoke 將操作釋出到user interface (UI) 執行緒的 Dispatcher 上。

 

參考部落格連結:

     http://www.cnblogs.com/DebugLZQ/archive/2012/08/05/2623669.html

     http://blog.csdn.net/luols/article/details/5880232

     http://www.360doc.com/content/11/0812/11/1039473_139824496.shtml

--------------------- 本文來自 在路上的工程師 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/qq_40691189/article/details/80196492?utm_source=copy