[C#].NET中幾種Timer的使用


這篇博客將梳理一下.NET中4個Timer類,及其用法。

1. System.Threading.Timer

public Timer(TimerCallback callback, object state, int dueTime, int period);

callback委托將會在period時間間隔內重復執行,state參數可以傳入想在callback委托中處理的對象,dueTime標識多久后callback開始執行,period標識多久執行一次callback。

using System.Threading;
// System.Threading.Timer

Timer timer = new Timer(delegate
{
    Console.WriteLine($"Timer Thread: {Thread.CurrentThread.ManagedThreadId}");

    Console.WriteLine($"Is Thread Pool: {Thread.CurrentThread.IsThreadPoolThread}");

    Console.WriteLine("Timer Action.");
},
null,
2000,
1000
);

Console.WriteLine("Main Action.");
Console.WriteLine($"Main Thread: {Thread.CurrentThread.ManagedThreadId}");

Console.ReadLine();

Timer回掉方法執行是在另外ThreadPool中一條新線程中執行的。

2. System.Timers.Timer

System.Timers.Timer和System.Threading.Timer相比,提供了更多的屬性,

Interval  指定執行Elapsed事件的時間間隔;

Elapsed  指定定期執行的事件;

Enabled  用於Start/Stop Timer;

Start    開啟Timer

Stop    停止Timer

System.Timers.Timer timer = new System.Timers.Timer();

timer.Interval = 500;

timer.Elapsed += delegate
{
    Console.WriteLine($"Timer Thread: {Thread.CurrentThread.ManagedThreadId}");

    Console.WriteLine($"Is Thread Pool: {Thread.CurrentThread.IsThreadPoolThread}");

    Console.WriteLine("Timer Action");

    timer.Stop();
};

timer.Start();

Console.WriteLine("Main Action.");
Console.WriteLine($"Main Thread: {Thread.CurrentThread.ManagedThreadId}");

Console.ReadLine();

Timer Elapsed定期任務是在ThreadPool的線程中執行的。

3. System.Windows.Forms.Timer

Interval  指定執行Elapsed事件的時間間隔;

Tick       指定定期執行的事件;

Enabled  用於Start/Stop Timer;

Start    開啟Timer

Stop    停止Timer

使用System.Windows.Forms.Timer來更新窗體中Label內時間,

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

Timer Tick事件中執行的事件線程與主窗體的線程是同一個,並沒有創建新線程(或者使用ThreadPool中線程)來更新UI。下面將代碼做一個改動,使用System.Timers.Timer來更新UI上的時間,代碼如下,

public Form1()
{
    InitializeComponent();

    this.Load += delegate
    {
        System.Timers.Timer timer = new System.Timers.Timer();

        timer.Interval = 500;

        timer.Elapsed += 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}");
    };
}

很熟悉的一個錯誤。因為Label是由UI線程創建的,所以對其進行修改需要在UI線程中進行。System.Timers.Timer中Elasped執行是在ThreadPool中新創建的線程中執行的。所以會有上面的錯誤。

4. System.Windows.Threading.DispatcherTimer

屬性和方法與System.Windows.Forms.Timer類似。

using System.Windows.Threading;

public MainWindow()
{
    InitializeComponent();

    this.Loaded += delegate
    {
        //DispatcherTimer

        DispatcherTimer timer = new DispatcherTimer();

        timer.Interval = TimeSpan.FromSeconds(1);

        timer.Start();

        Debug.WriteLine($"Main Thread Id: {Thread.CurrentThread.ManagedThreadId}");

        timer.Tick += delegate
        {
            tbTime.Text = DateTime.Now.ToLongTimeString();

            Debug.WriteLine($"Timer Thread Id: {Thread.CurrentThread.ManagedThreadId}");

            timer.Stop();
        };
    };
}

DispatcherTimer中Tick事件執行是在主線程中進行的。

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

DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Send);

感謝您的閱讀。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM