定時器是系統(tǒng)常用的組件之一,程序員可以根據(jù)自己的需求定制一個定時器類型,也可以使用.net內(nèi)建的定時器類型。在.net中一共為程序員提供了3種定時器:
- System.Windows.Forms.Timer類型
- System.Threading.Timer類型
- System.Timers.Timer類型
一、System.Windows.Forms.Timer
從這個定時器的命名空間可以看出,.net設計這個定時器的目的是為了方便程序員在Window Form中使用的定時器。當一個System.Windows.Forms.Timer類被構造時,當前定時器會和當前線程進行關聯(lián)。而當計時器的計滿后,一個定時器消息將被插入到當前線程的消息隊列中。當前線程逐一處理消息中的所有消息,并一一派發(fā)給各自的處理方法。這樣的機制和利用工作者進程定時有很大的區(qū)別,
System.Windows.Forms.Timer類型并沒有涉及多線程的操作,定時器的設置、定時方法的執(zhí)行都在同一個線程之上。這就意味著System.Windows.Forms.Timer并不能準確計時,尤其當消息阻塞時,定時器的誤差將會更大,因為定時器消息只能等待在前面的所有消息處理完后才能得到處理。但是因為System.Windows.Forms.Timer類型的定時器并不涉及多線程的操作,因此是線程安全的,不會發(fā)生回調(diào)方法重入的問題。
主要使用步驟如下:
1. System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();//實例化
2. myTimer.Tick += new EventHandler(函數(shù)名); //給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();
}
//回調(diào)函數(shù)
private void Callback(object sender, EventArgs e) {
//獲取系統(tǒng)時間 20:16:16
textBox1.Text = DateTime.Now.ToLongTimeString().ToString();
}
}}
二、System.Threading.Timer
這個定時器類的使用相對復雜,但同時它也是最優(yōu)化的非常常用的一個定時器類型。System.Threading.Timer的定時方法在獨立的線程上執(zhí)行,定時時間更為準確。使用回調(diào)方法的計時器,而且由線程池線程服務,簡單且對資源要求不高。所有的對象有一個線程控制,當下一個定時到達時,該線程會負責在線程中獲得一個新的工作者線程,用以執(zhí)行相應的回調(diào)方法。
雖然這個定時器是相對最優(yōu)化的一個定時器類型,但是從其機制上來講,其并不是線程安全的,可能會出現(xiàn)回調(diào)方法重入的問題。解釋下方法重入,是一個有關多線程編程的概念,意思大概是:同一程序中,多個線程同時運行時,就可能發(fā)生同一個方法被多個進程同時調(diào)用的情況。當這個方法中存在一些非線程安全的代碼時,方法重入會導致數(shù)據(jù)發(fā)生同步錯誤的bug。
主要使用步驟如下:
1、實例構造一個線程定時器。
System.Threading.Timer mytimer =
new System.Threading.Timer(new System.Threading.TimerCallback(timerCall), null, 0, 1000);
★timer構造函數(shù)資料:
public Timer(
TimerCallback callback, // TimerCallback 委托,表示要執(zhí)行的方法。
object state, //一個包含回調(diào)方法要使用的信息的對象,或者為 null。
int dueTime, //第一次執(zhí)行調(diào)用方法等待時間 // 指定零 (0) 可立即啟動計時器。
//指定零 (-1) 表示本定時器被禁用。
//Change(Int32,Int32)方法可以改寫定時器參數(shù)
int period // 執(zhí)行間隔時間
//如果 period 為零 (0) 或 -1 毫秒,而且dueTime 為正,則只會調(diào)用一次方法;
//然后計時器的定時行為將被禁用,使用 Change 可以改寫定時器參數(shù)。
)
2、編寫timerCall回調(diào)函數(shù)
格式:private void timerCall(object xxxxx) { .......; .......;}
3、使用Change(Int32,Int32)方法來修改定時器參數(shù)實現(xiàn)停止、重新開始等。
4、使用Dispose()方法釋放定時器資源。
System.Threading.Timer例程:
public startTimer()
{
//定義一個對象
System.Threading.Timer timer = new System.Threading.Timer(
new System.Threading.TimerCallback(Say), null, 0, 1000);
//1S定時器
}
//函數(shù)形式參數(shù)必須是object格式
public void Say(object a )
{
Console.WriteLine("你好");
}
using System;
using System.Threading;
class TimerExample
{
static void Main()
{
//創(chuàng)建一個事件來指示超時計數(shù)閾值 //定時器回調(diào)。
AutoResetEvent autoEvent = new AutoResetEvent(false);
StatusChecker statusChecker = new StatusChecker(10);
// 創(chuàng)建一個推斷的委托,調(diào)用計時器的方法。
TimerCallback tcb = statusChecker.CheckStatus;
// 創(chuàng)建一個指示委托調(diào)用的計時器。
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;
}
// 此方法由定時器委托調(diào)用。
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)
{
// 重置計數(shù)器和信號主信號。
invokeCount = 0;
autoEvent.Set();
}
}
}
三、 System.Timers.Timer類
這是一個相對較舊的類型,它和System.Threading.Timer一樣,可以由工作者線程來執(zhí)行回調(diào)方法,但同時它也可以在IDE環(huán)境中被拖到窗體控件上,這個時候它的行為非常類似于System.Windows.Forms.Timer類型,在消息過多時其定時并不準確?! ystem.Timers.Timer可以視為System.Threading.Timer的一個包裝,其類型設計相對古老,不建議使用該定時器。
主要使用步驟如下:
1. System.Timers.Timer myTimer = new System.Timers.Timer( 1000 ); //實例化 設置時間間隔
2. myTimer .Elapsed += new System.Timers.ElapsedEventHandler(函數(shù)名); //給timer掛起事件
3. myTimer .AutoReset = true; //設置是執(zhí)行一次(false)還是一直執(zhí)行(true);
4. myTimer .Enabled = true; //是否執(zhí)行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事件是觸發(fā)一次(false),還是一直觸發(fā)(true)
}
private void btnStart_Click(objectsender, EventArgs e)
{
t.Enabled = true; //是否觸發(fā)Elapsed事件
t.Start();
}
private void Timer_TimesUp(objectsender, System.Timers.ElapsedEventArgs e)
{
//到達指定時間5秒觸發(fā)該事件輸出 HelloWorld!!!!
System.Diagnostics.Debug.WriteLine("HelloWorld!!!!");
}
private void btnStop_Click(objectsender, EventArgs e)
{
t.Stop();
System.Diagnostics.Debug.WriteLine("未到指定時間5秒提前終結?。?!");
}
——本文并非原創(chuàng),如有侵權請聯(lián)系管理員刪除。