C#四種計時器Timer的區別和用法

1、System.Threading.Timer 線程計時器

1、最底層、輕量級的計時器。基於線程池實現的,工作在輔助線程。

2、它並不是內在線程安全的,並且使用起來比其他計時器更麻煩。此計時器通常不適合 Windows 窗體環境。

構造函數:public Timer(TimerCallback callback, object state, int dueTime, int period);

string state=”.”;
//state參數可以傳入想在callback委托中處理的對象。可以傳遞一個AutoRestEvent,在回調函數中向主函數發送信號。
Timer timer=new Timer(TimeMethod,state,100,1000)//100表示多久後開始,1000表示隔多久執行一次。

void TimerMethod(object state)
{Console.Write(state.ToString());}

timer.Dispose();//取消timer執行

2、System.Timers.Timer  服務器計時器

1、針對服務器的服務程序,基於System.Threading.Timer,被設計並優化成能用於多線程環境。在這種情況下,應該確保事件處理程序不與 UI 交互。在asp.net中一般使用System.Timers.Timer。

2、繼承自Compnent,公開瞭可以SynchronizingObject 屬性,避免瞭線程池中無法訪問主線程中組件的問題(模擬System.Windows.Forms.Timer單線程模式)。但是除非需要對事件的時間安排進行更精確的控制,否則還是應該改為使用 System.Windows.Forms.Timer。

3、AutoReset屬性設置計時器是否在引發Elapsed事件後重新計時,默認為true。如果該屬性設為False,則隻執行timer_Elapsed方法一次。

4、System.Timers.Timer是多線程定時器,如果一個Timer沒有處理完成,到達下一個時間點,新的Timer同樣會被啟動。所以,Timer比較適合執行不太耗時的小任務,若在Timer中運行耗時任務,很容易出現由於超時導致的多線程重入問題,即多個線程同時進入timer_Elapsed方法。

System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 500;
timer.SynchronizingObject = this;

timer.Elapsed+=new System.Timers.ElapsedEventHandler(timer_Elapsed);

timer.Start(); private void timer_Elapsed(Object source, Timers.ElapsedEventArgs e)
{
    this.tbTimer.Text = value;
}

5、為瞭應對多線程重入問題。可以加鎖,也可以增加標志位。 Interlocked.Exchange提供瞭一種輕量級的線程安全的給對象賦值的方法,所以使用Interlocked.Exchange給變量賦值。

int inTimer = 0;
        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Interlocked.Exchange(ref inTimer, 1) == 0)
            {
                Thread.Sleep(3000);
                string currentThreadId = Thread.CurrentThread.ManagedThreadId.ToString();
                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this.Label_Result.Content += currentThreadId + ",";
                }), null);
                Interlocked.Exchange(ref inTimer, 0);
            }
        }

3、System.Windows.Forms.Timer  Windows計時器

此計時器直接繼承自Component,它經過瞭專門的優化以便與 Windows 窗體一起使用,並且必須在窗口中使用。

  • Windows計時器建立在基於消息的UI線程上運行,精度限定為5ms。Tick事件中執行的事件與主窗體是同一個線程(單線程),並且對與 UI 交互是安全的。
  • 隻有Enable和Internal兩個屬性和一個Tick事件,可以使用Start()和Stop()方法控制Enable屬性。
using System.Windows.Forms;

public Form1()
{
    InitializeComponent();
    this.Load += delegate
    {
        Timer timer = new Timer();
        timer.Interval = 500;
        timer.Tick += delegate
        {
            System.Diagnostics.Debug.WriteLine($"Timer Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
            System.Diagnostics.Debug.WriteLine($"Is Thread Pool: {System.Threading.Thread.CurrentThread.IsThreadPoolThread}");
            this.lblTimer.Text = DateTime.Now.ToLongTimeString();
        };

        timer.Start();
        System.Diagnostics.Debug.WriteLine($"Main Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
    };
}

4. System.Windows.Threading.DispatcherTimer

主要用於WPF中。屬性和方法與System.Windows.Forms.Timer類似。DispatcherTimer中Tick事件執行是在主線程中進行的。

使用DispatcherTimer時有一點需要註意,因為DispatcherTimer的Tick事件是排在Dispatcher隊列中的,當系統在高負荷時,不能保證在Interval時間段執行,可能會有輕微的延遲,但是絕對可以保證Tick的執行不會早於Interval設置的時間。如果對Tick執行時間準確性高可以設置DispatcherTimer的priority。

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: