在C#中存在3種經常使用的 Timer :服務器
這個 Timer 是單線程的,也就是說只要它運行,其餘線程就要等着。多線程
這個 Timer 有以下特色:函數
從上面的第一個特色能夠得知,該 Timer 會形成 WinForm UI 假死,所以若是須要定時處理大量計算或者大量IO操做的任務,不建議使用該 Timer ,接下來咱們看一個例子體會一下在IO操做的狀況下出現的假死狀況:this
咱們在Form中放入兩個Button 一個Lable和一個Timerspa
private void Button_Click(object sender, EventArgs e) { timer.Interval = 1000; timer.Tick += Timer_Tick; timer.Start(); } private void Timer_Tick(object sender, EventArgs e) { for (int i = 0; i < 10000; i++) { File.AppendAllText(Directory.GetCurrentDirectory()+"test.txt", i.ToString()); this.label_output.Text = "當前操做:插入數字" + i; } }
咱們單擊計算按鈕,咱們會發現WinForm出現了假死(沒法移動窗口、按鈕沒法點擊等)操作系統
該 Timer 是基於服務器的計時器,是爲在多線程環境中用於輔助線程而設計的,能夠在線程間移動來處理引起的 Elapsed 事件,比上一個計時器更加精確。線程
該 Timer 有以下特色:設計
一樣咱們經過代碼來看一下該 Timer 計時器怎麼使用:code
System.Timers.Timer timersTimer = new System.Timers.Timer(); private void Button_Click(object sender, EventArgs e) { timersTimer.Interval = 1000; timersTimer.Enabled = true; timersTimer.Elapsed += TimersTimer_Elapsed; timersTimer.Start(); } private void TimersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { for (int i = 0; i < 10000; i++) { this.BeginInvoke(new Action(() => { this.label_output.Text="當前時間:"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); }), null); } } private void Button1_Click(object sender, EventArgs e) { timersTimer.Stop(); }
運行上面代碼,會發現WinForm界面假死的狀況消失了。orm
該 Timer 一樣也是一個多線程的計時器,它有以下特色:
咱們來看一下代碼(在控制檯應用程序中輸入如下代碼):
static System.Threading.Timer threadingTimer; static int numSum = 0; static void Main(string[] args) { threadingTimer = new System.Threading.Timer(new System.Threading.TimerCallback(threadingTimer_Elapsed), null, 0, 1000); Console.Read(); } private static void threadingTimer_Elapsed(object state) { for (int i = 0; i < 10000; i++) { numSum++; Console.WriteLine("輸出數字:"+i); } if (numSum > 10000) { threadingTimer.Dispose(); Console.WriteLine("結束"); } }
注意:當咱們再也不須要多線程Timer計時器的時候,咱們能夠調用 Dispose 方法釋放所佔有的資源。可是由於Timer計時器是按線程池線程來安排回調執行的,所以回調可能發生在 Dispose方法的重載被調用以後,因此咱們可使用可以使用 Dispose(WaitHandle) 方法等待全部回掉完成。