LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

.NET中有多少種定時器

freeflydom
2023年11月29日 9:44 本文熱度 773

.NET中至少有6種定時器,每一種定時器都有它的用途和特點。根據定時器的應用場景,可以分為UI相關的定時器和UI無關的定時器。本文將簡單介紹這6種定時器的基本用法和特點。

UI定時器#

.NET中的UI定時器主要是WinForm、WPF以及WebForm中的定時器。分別為:

  • System.Windows.Forms.Timer

  • System.Windows.Threading.DispatcherTimer

  • System.Web.UI.Timer

通常情況下,WinForm、WPF中的定時器是在UI線程上執行回調函數,因此可以直接訪問UI元素。由于WinForm、WPF支持單線程單元模型(Single-Thread Apartment,STA),定時器間隔事件是在UI線程上觸發,因此,不用擔心線程安全問題。
System.Web.UI.Timer是通過Javascript定時器和服務端異步回調實現,也是單線程的。

請注意,這里說的是通常情況,后邊介紹System.Windows.Threading.DispatcherTimer時會提到在非UI線程創建DispatcherTimer時也無法直接訪問UI元素。

System.Windows.Forms.Timer#

System.Windows.Forms.Timer針對WinForm應用進行了優化,是只能在WinForm上使用的定時器。這個定時器是針對單線程環境設計的,是在UI線程上處理定時任務。
它要求用戶代碼有可用的UI消息泵,定時任務須在UI線程上運行,或者跨線程通過Invoke或者BeginInvoke封送(marshal)到UI線程上運行。其優點是使用簡單,只需通過給Interval屬性賦值來設置時間間隔,并注冊Tick事件處理定時任務。其缺點是精度不高,精度為55毫秒,也就是Interval賦值小于55時,也是55毫秒觸發一次定時任務。

public partial class Timerfrom : Form

{

    private System.Windows.Forms.Timer digitalClock;

    private void Timerfrom_Load(object sender, EventArgs e)

    {

        digitalClock = new System.Windows.Forms.Timer();//創建定時器 

        digitalClock.Tick += new EventHandler(HandleTime);//注冊定時任務事件 

        digitalClock.Interval = 1000;//設置時間間隔

        digitalClock.Enabled = true;

        digitalClock.Start(); //開啟定時器

    }

    public void HandleTime(Object myObject, EventArgs myEventArgs)

    {

        labelClock.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

    }

    private void frmTimerDemo_FormClosed(object sender, FormClosedEventArgs e)

    {

        digitalClock.Stop();//停止定時器

        digitalClock.Dispose();

    }

}

System.Windows.Threading.DispatcherTimer#

System.Windows.Threading.DispatcherTimer是WPF中的定時器,它是基于Dispatcher對象的(并不是基于UI線程的)。DispatcherTimer的定時任務是像其他操作一樣放在Dispatcher隊列上,其執行操作時間依賴于隊列中其他任務及其優先級,因此,DispatcherTimer不保證在時間間隔發生時準確執行,只保證不會在時間間隔發生前執行。

Dispatcher為特定線程維護工作項(操作)的優先級隊列,在線程上創建Dispatcher對象時,它成為唯一可以關聯該線程的Dispatcher對象,WPF中,DispatcherObject只能被與之關聯的Dispatcher對象訪問,也就是非UI線程中無法直接訪問UI元素(WPF中的UI元素都是派生自DispatcherObject

此外,DispatcherTimer不像System.Windows.Forms.Timer那樣只在UI線程上創建才能觸發Tick事件,它在非UI線程下創建也可以觸發Tick事件,此時訪問UI元素也需要通過Invoke或者BeginInvoke封送(marshal)到UI線程上運行。其優點也是簡單易用,適合在UI線程上執行任務或觸發事件,缺點是精度不準確,可能存在延遲。

private void Dt_Tick(object sender, EventArgs e)

{

    Dispatcher.BeginInvoke((Action)delegate ()

    {

        text1.Text = DateTime.Now.ToString();

    });

    Console.WriteLine(DateTime.Now.ToString());

}


private void Button_Click(object sender, RoutedEventArgs e)

{

    Task.Run(() =>{

        DispatcherTimer dt = new DispatcherTimer();

        dt.Tick += Dt_Tick;

        dt.Interval = TimeSpan.fromSeconds(1);

        dt.Start();

        Dispatcher.Run();

    });

}

上述代碼中,DispatcherTimer是非UI線程中創建,定時任務中訪問UI元素text1,需要通過Invoke或者BeginInvoke封送(marshal)到UI線程上運行,而Console.WriteLine則可以直接運行。

System.Web.UI.Timer#

System.Web.UI.Timer是僅適用于.NET FrameworkASP.NET組件。通過Javascript定時器和服務端異步回調實現。每次觸發定時器時,只能執行一個異步回調方法,而其他的異步回調方法需要等待前一個異步回調方法執行完畢后才能執行。這樣可以保證在任意時刻只有一個異步回調方法在執行,避免了多線程并發執行的問題。

UI無關定時器#

從 .NET 6開始,UI無關定時器有三個:

  • System.Threading.Timer

  • System.Timers.Timer

  • System.Threading.PeriodicTimer(.NET 6+)

System.Threading.Timer#

System.Threading.Timer是最基礎輕量的定時器,它將定期在線程池線程上執行單個回調方法。在創建定時器對象時必須指定回調方法,并且后續不能修改,同時也可以指定定時器回調開始執行的時間以及時間間隔。定時器創建后可以通過Change方法修改回調開始執行的時間以及時間間隔。該定時器的優點是輕量,精度相對較高,與Windows操作系統時鐘精度一致,大約15毫秒。但因為是基于線程池的,所以在任務執行時間較長或者線程池過載時,會出現延遲。其缺點是使用不太方便,定時器創建后無法修改回調方法。

var stateTimer = new 

var autoEvent = new AutoResetEvent(false);

Timer(CheckStatus, autoEvent, 1000,250);


private int invokeCount=0;


public void CheckStatus(Object stateInfo)

{

    AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;

    Console.WriteLine("{0} Checking status {1,2}.",DateTime.Now.ToString("h:mm:ss.fff"),(++invokeCount).ToString());


    if(invokeCount == 10)

    {

        invokeCount = 0;

        autoEvent.Set();

    }

}

System.Timers.Timer#

System.Timers.Timer在內部使用System.Threading.Timer,并公開了更多的屬性,如AutoResetEnabledSynchronizingObject,這些屬性允許配置回調的執行方式。此外,Tick事件允許注冊多個處理程序。因此,一個定時器可以觸發多個處理程序。還可以在計時器啟動后更改處理程序。與System.Threading.Timer相似,其優點也是精度相對較高,與Windows操作系統時鐘精度一致,大約15毫秒。因為默認(或者SynchronizingObject=null時)是基于線程池的,所以在任務執行時間較長或者線程池過載時,會出現延遲。但使用要更簡便一些。

public partial class Timerfrom : Form

{

    private System.Timers.Timer timer;

    private void Timerfrom_Load(object sender, EventArgs e)

    {

        // 支持注冊多個處理程序

        timer.Elapsed += (sender, e) => { label1.Text = DateTime.Now.ToLongTimeString(); };

        timer.Elapsed += (sender, e) => { Console.WriteLine(DateTime.Now.ToLongTimeString()); };

        //自定義回調執行的方式(指定對象所在的線程),SynchronizingObject=null時在線程池上執行

        timer.SynchronizingObject = this;

        timer.AutoReset = true;

        timer.Start();

    }

}

本例中將SynchronizingObject屬性設置為Form對象,因此Elapsed的處理程序在UI線程上執行,可以直接修改label1.Text,如果SynchronizingObject屬性為null,處理程序則是在線程池線程上執行,修改label1.Text時需要通過Invoke或者BeginInvoke封送(marshal)到UI線程上運行。

System.Threading.PeriodicTimer#

System.Threading.PeriodicTimer是 .NET 6中引入的定時器。它能方便地使用異步方式,它沒有Tick事件,而是提供WaitForNextTickAsync方法處理定時任務。通常是使用While循環結合CancellationToken一起使用。和CancellationToken一起用的時候需要注意,如果CancellationToken被取消的時候會拋出一個OperationCanceledException需要考慮自己處理異常。相比之前的定時器來說,有下面幾個特點:

  1. 沒有callback 來綁定事件;

  2. 不會發生重入,只允許有一個消費者,不允許同一個PeriodicTimer在不同的地方同時WaitForNextTickAsync,不需要自己做排他鎖來實現不能重入;

  3. 異步化。之前的 timer 的 callback 都是同步的,使用新 timer 可以使用異步方法,避免了編寫 Sync over Async 代碼;

  4. Dispose 之后,實例就無法使用,并且 WaitForNextTickAsync 始終返回 false。

var cts = new CancellationTokenSource(TimeSpan.fromSeconds(15));

using (var timer = new PeriodicTimer(TimeSpan.fromSeconds(1)))

{

    try

    {

        while (await timer.WaitForNextTickAsync(cts.Token))

        {

            await Task.Delay(3000);

            Console.WriteLine($"ThreadId is {Thread.CurrentThread.ManagedThreadId} --- Time is {DateTime.Now:HH:mm:ss}");

        }

    }

    catch (OperationCanceledException)

    {

        Console.WriteLine("Operation cancelled");

    }

}

小結#

我們在開發過程中遇到的坑往往不是技術本身的坑,而是我們濫用沒有掌握的技術導致的,在有多種技術方案可選的時候,通常只關注技術的優點,忽略了技術適用場景及其局限性。.NET中幾種定時器各自都有其適用場景和不足,但都不支持高精度計時。了解這些有助于我們在開發過程中選擇合適定時器,避免遇到問題后被動地替換解決方案。


  1. https://xie.infoq.cn/article/6aa23b6850abddf717a6c9fc9 ↩︎

作者:czwy

出處:https://www.cnblogs.com/czwy/p/17862702.html

版權:本作品采用「署名-相同方式共享 4.0 國際」許可協議進行許可。



該文章在 2023/11/29 9:44:39 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
日韩新片免费专区在线观看 | 亚洲国产另类久久久精品女同 | 亚洲欧美人成综合在线另类 | 欧美国产日本高清不卡 | 五月婷婷亚洲综合视频 | 亚洲五月婷婷久久综合色 |