在.NET Framework里面提供了三種Timer
① System.Windows.Forms.Timer
② System.Timers.Timer
③ System.Threading.Timer
一、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 button1_Click(object sender, 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(3000);
}
}
}
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} {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線程,導致界面卡死等占用資源的情況。
相關參考:
1、https://blog.csdn.net/aoxuefeihu/article/details/7483227
2、https://blog.csdn.net/lzp_k2/article/details/84102066
https://blog.csdn.net/lzp_k2/article/details/84102066