天天看點

深入淺出多線程系列之七:4種定時器

在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方法。

深入淺出多線程系列之七:4種定時器

       public  static  void Main ()

        {

             // 5秒後開始運作,接着每隔1秒的調用Tick方法

            Timer tmr =  new Timer(Tick,  " tick... ",  5000,  1000);

            Console.ReadLine();

            tmr.Dispose();

        }

         static  void Tick( object data)

        {

            Console.WriteLine(data);

        }

深入淺出多線程系列之七:4種定時器

.net framework提供的另一個計時器System.Timers.Timer.簡單的對System.Threading.Timer進行了包裝。增加了下面幾個特性。

  1. 實作了Component,是以可以在設計器顯示。
  2. 代替Change方法的一個Interval屬性
  3. 代替callback委托的一個Elapsed事件
  4. 啟動和停止timer的Enabled屬性,預設是false。
  5. 為了避免Enabled造成混亂,提供了Start和Stop方法。
  6. 是否在每次指定的間隔結束時引發Elapsed時間,還是僅間隔第一次結束後運作的AutoReset屬性。
  7. 在WPF或Windows Forms中安全的調用方法的SynchronizingObject對象。
深入淺出多線程系列之七:4種定時器

public  static  void MainThread()

        {

            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... ");

        }

深入淺出多線程系列之七:4種定時器

單線程計時器:

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消息。

下面是它們的優點:

  1. 你可以忘記線程安全。
  2. 一個Tick事件在前一個Tick事件被處理完畢前不會被觸發。
  3. 你可以直接在Tick事件處理代碼中更新控件,不需要調用Control.Invoke或Dispatcher.Invoke.

看下在Winform中使用單線程定時器的效果:

深入淺出多線程系列之七:4種定時器

       // 基于Windows消息循環的單線程計時器

         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);

        }

深入淺出多線程系列之七:4種定時器

如果運作上面的代碼,會發現UI界面響應速度很慢,

原理上面已經介紹了:單線程計時器基于Windows消息循環,應用程式會同步的處理計時器的消息。

解決這個問題的方法是使用多線程計時器:隻要修改代碼使用多線程計時器即可:

深入淺出多線程系列之七:4種定時器

        // 使用多線程計時器

         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);

        }

深入淺出多線程系列之七:4種定時器

上面的例子告訴我們單線程計時器的缺點:

除非Tick事件的處理代碼執行的非常快,否則UI界面會變得響應很慢。 

是以 WPF和Windows Forms的計時器都非常适合小任務,尤其是界面更新的任務。例如時鐘和計數顯示。否則,你需要一個多線程計時器。

參考資料:

http://www.albahari.com/threading/