定時器是系統常用的組件之一,程式員可以根據自己的需求定製一個定時器類型,也可以使用.net內建的定時器類型。在.net中一共為程式員提供了3種定時器: System.Windows.Forms.Timer類型 System.Threading.Timer類型 System.Timers.Timer類 ...
定時器是系統常用的組件之一,程式員可以根據自己的需求定製一個定時器類型,也可以使用.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秒提前終結!!!"); }
參考鏈接: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