在Framework中存在着4種定時器:其中分爲兩類,
多線程計時器
1:System.Threading.Timer
2:System.Timers.Timer
特殊目的的單線程計時器:
1:System.Windows.Forms.Timer(Windows Forms Timer)
2:System.Windows.Threading.DispatcherTimer(WPF timer);
多線程計時器比較強大,精確,而且可擴展性強;
單線程計時器比較安全,對於更新 Windows Forms controls或者WPF這種簡單任務來說更方便。
System.Threading.Timer是最簡單的多線程計時器。在下面的例子中,定時器在5秒後開始定時1秒的調用Tick方法。
{
//5秒後開始運行,接着每隔1秒的調用Tick方法
Timer tmr = new Timer(Tick, "tick...", 5000, 1000);
Console.ReadLine();
tmr.Dispose();
}
static void Tick(object data)
{
Console.WriteLine(data);
}
.net framework提供的另一個計時器System.Timers.Timer.簡單的對System.Threading.Timer進行了包裝。增加了下面幾個特性。
- 實現了Component,所以可以在設計器顯示。
- 代替Change方法的一個Interval屬性
- 代替callback委託的一個Elapsed事件
- 啓動和停止timer的Enabled屬性,默認是false。
- 爲了避免Enabled造成混亂,提供了Start和Stop方法。
- 是否在每次指定的間隔結束時引發Elapsed時間,還是僅間隔第一次結束後運行的AutoReset屬性。
-
在WPF或Windows Forms中安全的調用方法的SynchronizingObject對象。
{
Timer tmr = new Timer();
tmr.Interval = 500;
tmr.Elapsed += new ElapsedEventHandler(tmr_Elapsed);
tmr.Start();
Console.ReadLine();
tmr.Stop();
Console.ReadLine();
tmr.Start();
Console.ReadLine();
tmr.Dispose();
}
static void tmr_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Tick...");
}
單線程計時器:
1:System.Windows.Forms.Timer(Windows Forms Timer)
2:System.Windows.Threading.DispatcherTimer(WPF timer);
單線程計時器是被設計成屬於他們執行環境的計時器,如果你在一個Windows服務應用程序中使用Windows Forms的Timer,timer 事件並不會被觸發,只有在對應的環境下才會被觸發。
像System.Timers.Timer一樣,他們也提供了相同的成員(Interval,Tick,Start,Stop),但是他們內部的工作原理不同,
WPF和Windows Forms的計時器使用消息循環機制來取代線程池產生消息的機制。
這意味着Tick事件總是在創建timer的那個線程上執行,同時也意味着如果上一個Tick消息還未被處理,即使時間超過了間隔時間,在消息循環中也只存在一個Tick消息。
下面是它們的優點:
-
你可以忘記線程安全。
-
一個Tick事件在前一個Tick事件被處理完畢前不會被觸發。
-
你可以直接在Tick事件處理代碼中更新控件,不需要調用Control.Invoke或Dispatcher.Invoke.
看下在Winform中使用單線程定時器的效果:
private System.Windows.Forms.Timer timer = new Timer() { };
public Form1()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick);
timer.Enabled = true;
}
void timer_Tick(object sender, EventArgs e)
{
//模擬的做一些耗時的操作
System.Threading.Thread.Sleep(2000);
}
如果運行上面的代碼,會發現UI界面響應速度很慢,
原理上面已經介紹了:單線程計時器基於Windows消息循環,應用程序會同步的處理計時器的消息。
解決這個問題的方法是使用多線程計時器:只要修改代碼使用多線程計時器即可:
private System.Timers.Timer timer = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//模擬的做一些耗時的操作
System.Threading.Thread.Sleep(2000);
}
上面的例子告訴我們單線程計時器的缺點:
除非Tick事件的處理代碼執行的非常快,否則UI界面會變得響應很慢。
所以 WPF和Windows Forms的計時器都非常適合小任務,尤其是界面更新的任務。例如時鐘和計數顯示。否則,你需要一個多線程計時器。
參考資料:
http://www.albahari.com/threading/
CLR Via C# 3.0