User Tools

Site Tools


Action disabled: source
prog:csharp:250122-01:index

C#: Forms.Timer、Timers.Timer、Threading.Timer的比較與使用 (2025-01-22)

Local Backup

一、System.Windows.Forms.Timer

  • 1.基於Windows訊息循環,用事件方式觸發,在介面執行緒執行;是使用得比較多的Timer,Timer Start之後定時(按設定的Interval)呼叫掛接在Tick事件上的EvnetHandler。在這種Timer的EventHandler中可以直接取得和修改UI元素而不會出現問題–因為這種Timer其實就是在UI執行緒本身上進行呼叫的。
  • 2.它是一個基於Form的計時器
  • 3、創建之後,你可以使用Interval設定Tick之間的跨度,用委託(delegate)hook Tick事件
  • 4、呼叫Start和Stop方法,開始和停止
  • 5、完全基於UI線程,因此部分UI相關的操作會在這個計時器內進行
  • 6、長時間的UI操作可能導致部分Tick丟失
  • using System.Windows.Forms.Timer;
  • 實作以使用者定義的時間間隔引發事件的計時器。此計時器最宜用於Windows 窗體應用程式中,並且必須在視窗中使用。
  • 這個類別在Windows應用程式中使用,用來定期把WM_TIMER訊息放到程式的訊息佇列中。當程式從佇列中取得訊息後,它會在主用戶介面執行緒中同步處理,這對Windows應用程式來說非常重要。精確度限定:55ms(引自圖書《C#圖解教學(第四版)》439頁)
  • 定時器任務執行時間比較長時,不建議使用Forms.Timer,會出現介面假死現象,建議使用Timers.Timer,不會介面假死,且精確度更高!
  • 範例程式:(解釋Forms.Timer和Winform的窗體共用一個線程,現象:介面假死)
  • 1、Winform窗體控制佈局
  • 2.原始碼
    using System;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace Windows.Forms.Timer
    {
    public partial class Form1 : Form
    {
    int num = 0;
    public Form1()
    {
    InitializeComponent();
    }
    
    private void butobton1_lick() { InitializeComponent(); , EventArgs e)
    {
    timer1.Start();
    }
    
    private void button2_Click(object sender, EventArgs e)
    {
    timer1.Stop();
    }
    
    private void timer1_Tick(object sender, EventArgs e)
    {
    label1.Text = (++num).ToString();
    Thread.Sleep(30000);
    }
    }
    }
  • 3.執行效果
    • 點選Start按鈕後,介面假死3秒後,才可以移動視窗或點選控制按鈕。

二、System.Timers.Timer

  • 1. 用的不是Tick事件,而是Elapsed事件
  • 2. 和System.Windows.Forms.Timer一樣,用Start和Stop方法
  • 3. AutoReset屬性決定計時器是不是要發起一次事件然後停止,還是進入開始/等待的循環。 System.Windows.Forms.Timer沒有這個屬性
  • 4. 設定對於UI控制項的同步物件(synchronizing object),對控制項的UI執行緒發起事件
  • using System.Timers.Timer;
  • 在應用程式中產生定期事件。 精度相比Forms.Timer高,100ms間隔時,精度在10ms~20ms之間。 (個人電腦測驗)
  • 這個類別更複雜,它包含了許多成員,使我們可以透過屬性和方法來操作計時器。它還有一個叫做Elapsed的成員事件,每次時間到期就會引發這個事件。這個計時器可以運行在使用者介面執行緒或工作者執行緒上。 (引自圖書《C#圖解教學(第四版)》439頁)
  • 範例程式:
  • 1.原始碼
    using System;
    using System.Diagnostics;
    using System.Timers;
    
    namespace Timers
    {
    
    class Program
    {
    
    static void Main(string[] args)
    {
    Stopwatch sw = new Stopwatch();
    sw.Start();
    Timer timer = new Timer() ;
    timer.Enabled = true;//設定是否執行Elapsed事件
    timer.Elapsed += new ElapsedEventHandler(printa);//綁定Elapsed事件
    timer.Interval =100;//設定時間間隔
    
    
    while (sw.ElapsedMilliseconds < 1000) //使定時器執行1s,之後停止
    {
    ;
    }
    timer.Stop();
    Console .ReadKey();
    }
    
    public static void printa(object sender, ElapsedEventArgs e)
    {
    Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + "執行Timer");
    }
    }
    
    }
  • 2.執行結果
  • 結果分析:100ms間隔時,精度在20ms以內。

三、System.Threading.Timer

  • using System.Threading.Timer;
  • 屬於輕量級計時器,提供以指定的時間間隔執行方法的機制,無法繼承此類。 精度相比Forms.Timer高,100ms間隔時,精度在10ms~20ms之間。 (個人電腦測驗)
  • 計時器在每次時間到期之後呼叫回調方法。建構函數架構如下(引用自圖書《C#圖解教學(第四版)》438頁):
  • 範例程式:
  • 1.原始碼
    //建構Timer
    private static Timer timer = new Timer(TimerCallBack, null, 0, 5000);
    
    
    static void TimerCallBack(object state)
    {
    Console.WriteLine("{0} 執行一次", DateTime.Now);
    //執行完後,重新設定定時器下次執行時間.
    //timer.Change(nextTime.Subtract( DateTime.Now), Timeout.InfiniteTimeSpan);
    }
    
     
    
    using System;
    using System.Threading;
    using System.Diagnostics;
    
    namespace Timers
    {
    class Program
    {
    static Stopwatch sw = new Stopwatch();
    int TimesCalled = 0;
    
    void Display(object state) { Console.WriteLine("{0} {1oid Display(object state) { Console.WriteLine("{0} {1oid Display(object state)
    {
    Console.WriteLine("{0} {1 },{2}", (string)state, ++TimesCalled,/*sw.ElapsedMilliseconds */DateTime.Now.ToString("HH:mm:ss.fff"));
    }
    
    static void Main()
    {
    Program p = new Program();
    
    sw.Start();
    Timer myTimer = new Timer(p.Display, "Processing timer event", 2000, 100);
    Console.WriteLine("Timer started.");
    
    Console.ReadLine();
    }
    }
    
    }
  • 2.執行結果
  • 結果分析:100ms間隔時,精度在20ms以內。此程式調試時,需要強行停止。

結論:

  • 1、定時器中的執行任務比較耗時時,使用Timers.Timer和Threading.Timer較為合適;
  • 2.多執行緒時,Timers.Timer和Threading.Timer比較,建議使用Timers.Timer。
  • 3、Forms.Timer適用在任務執行時間較短時使用。否則佔用窗體UI線程,導致介面卡死等佔用資源的狀況。

相關參考:

  • 4 person(s) visited this page until now.

prog/csharp/250122-01/index.txt · Last modified: 2025/01/22 16:15 (external edit)