C# 三個Timer

在C#中存在3種經常使用的 Timer服務器

  1. System.Windows.Forms.Timer
  2. System.Timers.Timer
  3. System.Threading.Timer

零、System.Windows.Forms.Timer

這個 Timer 是單線程的,也就是說只要它運行,其餘線程就要等着。
ZElKBR.gif多線程

這個 Timer 有以下特色:函數

  1. 徹底基於UI線程,定時器觸發時,操做系統把定時器消息插入線程消息隊列中,調用線程執行一個消息泵提取消息,而後發送到回調方法Tick中;
  2. 使用 StartStop 啓動和中止 Timer;
  3. UI操做過長會致使 Tick 丟失;
  4. 可使用委託Hook Tick事件;
  5. 精確度不高;
  6. 經過將 Enabled 設置爲 True,使 Timer 自動運行

從上面的第一個特色能夠得知,該 Timer 會形成 WinForm UI 假死,所以若是須要定時處理大量計算或者大量IO操做的任務,不建議使用該 Timer ,接下來咱們看一個例子體會一下在IO操做的狀況下出現的假死狀況:this

咱們在Form中放入兩個Button 一個Lable和一個Timer
ZetMuV.pngspa

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出現了假死(沒法移動窗口、按鈕沒法點擊等)操作系統

1、System.Timers.Timer

該 Timer 是基於服務器的計時器,是爲在多線程環境中用於輔助線程而設計的,能夠在線程間移動來處理引起的 Elapsed 事件,比上一個計時器更加精確。線程

該 Timer 有以下特色:設計

  1. 經過 Elapsed 設置回掉處理事件,且 Elapsed 是運行在 ThreadPool 上的;
  2. 經過 Interval 設置間隔時間;
  3. AutoReset 設置爲 False 時,只在到達第一次時間間隔後觸發 Elapsed 事件;
  4. 是一個多線程計時器;
  5. 沒法直接調用 WinForm 上的控件,須要使用 委託
  6. 主要用在 Windows 服務中。

一樣咱們經過代碼來看一下該 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

2、System.Threading.Timer

該 Timer 一樣也是一個多線程的計時器,它有以下特色:

  1. 多線程
  2. 和前兩個計時器相比沒有 StartStop 方法,若是要中止計時器,必須調用 Dispose 方法來銷燬 Timer 對象;
  3. 調用 Dispose 方法後並不能立刻中止全部的計時器,這是由於間隔時間小於執行時間時多個線程運行形成的,多個線程沒法同時中止;

ZeDVl4.gif

  1. 是一個輕量級的計時器;
  2. 全部的參數所有在構造函數中進行了設置;
  3. 能夠設置啓動時間;
  4. 不建議再 WinForm 程序中使用。

咱們來看一下代碼(在控制檯應用程序中輸入如下代碼):

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) 方法等待全部回掉完成。
相關文章
相關標籤/搜索