C#四種計(jì)時(shí)器Timer的區(qū)別和用法
1、System.Threading.Timer 線程計(jì)時(shí)器
1、最底層、輕量級(jí)的計(jì)時(shí)器。基于線程池實(shí)現(xiàn)的,工作在輔助線程。
2、它并不是內(nèi)在線程安全的,并且使用起來比其他計(jì)時(shí)器更麻煩。此計(jì)時(shí)器通常不適合 Windows 窗體環(huán)境。
構(gòu)造函數(shù):public Timer(TimerCallback callback, object state, int dueTime, int period);
string state=”.”; //state參數(shù)可以傳入想在callback委托中處理的對(duì)象。可以傳遞一個(gè)AutoRestEvent,在回調(diào)函數(shù)中向主函數(shù)發(fā)送信號(hào)。 Timer timer=new Timer(TimeMethod,state,100,1000)//100表示多久后開始,1000表示隔多久執(zhí)行一次。 void TimerMethod(object state) {Console.Write(state.ToString());} timer.Dispose();//取消timer執(zhí)行
2、System.Timers.Timer 服務(wù)器計(jì)時(shí)器
1、針對(duì)服務(wù)器的服務(wù)程序,基于System.Threading.Timer,被設(shè)計(jì)并優(yōu)化成能用于多線程環(huán)境。在這種情況下,應(yīng)該確保事件處理程序不與 UI 交互。在asp.net中一般使用System.Timers.Timer。
2、繼承自Compnent,公開了可以SynchronizingObject 屬性,避免了線程池中無法訪問主線程中組件的問題(模擬System.Windows.Forms.Timer單線程模式)。但是除非需要對(duì)事件的時(shí)間安排進(jìn)行更精確的控制,否則還是應(yīng)該改為使用 System.Windows.Forms.Timer。
3、AutoReset屬性設(shè)置計(jì)時(shí)器是否在引發(fā)Elapsed事件后重新計(jì)時(shí),默認(rèn)為true。如果該屬性設(shè)為False,則只執(zhí)行timer_Elapsed方法一次。
4、System.Timers.Timer是多線程定時(shí)器,如果一個(gè)Timer沒有處理完成,到達(dá)下一個(gè)時(shí)間點(diǎn),新的Timer同樣會(huì)被啟動(dòng)。所以,Timer比較適合執(zhí)行不太耗時(shí)的小任務(wù),若在Timer中運(yùn)行耗時(shí)任務(wù),很容易出現(xiàn)由于超時(shí)導(dǎo)致的多線程重入問題,即多個(gè)線程同時(shí)進(jìn)入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、為了應(yīng)對(duì)多線程重入問題??梢约渔i,也可以增加標(biāo)志位。 Interlocked.Exchange提供了一種輕量級(jí)的線程安全的給對(duì)象賦值的方法,所以使用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計(jì)時(shí)器
此計(jì)時(shí)器直接繼承自Component,它經(jīng)過了專門的優(yōu)化以便與 Windows 窗體一起使用,并且必須在窗口中使用。
- Windows計(jì)時(shí)器建立在基于消息的UI線程上運(yùn)行,精度限定為5ms。Tick事件中執(zhí)行的事件與主窗體是同一個(gè)線程(單線程),并且對(duì)與 UI 交互是安全的。
- 只有Enable和Internal兩個(gè)屬性和一個(gè)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事件執(zhí)行是在主線程中進(jìn)行的。
使用DispatcherTimer時(shí)有一點(diǎn)需要注意,因?yàn)镈ispatcherTimer的Tick事件是排在Dispatcher隊(duì)列中的,當(dāng)系統(tǒng)在高負(fù)荷時(shí),不能保證在Interval時(shí)間段執(zhí)行,可能會(huì)有輕微的延遲,但是絕對(duì)可以保證Tick的執(zhí)行不會(huì)早于Interval設(shè)置的時(shí)間。如果對(duì)Tick執(zhí)行時(shí)間準(zhǔn)確性高可以設(shè)置DispatcherTimer的priority。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
UGUI ScrollRect實(shí)現(xiàn)帶按鈕翻頁支持拖拽
這篇文章主要為大家詳細(xì)介紹了UGUI ScrollRect實(shí)現(xiàn)帶按鈕翻頁支持拖拽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05親自教你實(shí)現(xiàn)棧及C#中Stack源碼分析
大家都知道棧的實(shí)現(xiàn)方式有兩種,一種是基于數(shù)組實(shí)現(xiàn)的順序棧,另一種是基于鏈表實(shí)現(xiàn)的鏈?zhǔn)綏!_@篇文章主要介紹了手把手教你實(shí)現(xiàn)棧以及C#中Stack源碼分析,需要的朋友可以參考下2021-09-09在Parallel中使用DbSet.Add()發(fā)現(xiàn)的一系列多線程問題和解決思路詳解
這篇文章主要介紹了在Parallel中使用DbSet.Add()發(fā)現(xiàn)的一系列多線程問題和解決過程的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11C# mysql 插入數(shù)據(jù),中文亂碼的解決方法
用C#操作mysql時(shí), 插入數(shù)據(jù)中文都是亂碼,只顯示問號(hào),數(shù)據(jù)庫本身使用的是utf-8字符2013-10-10WPF使用Accord實(shí)現(xiàn)屏幕錄制功能
這篇文章主要為大家詳細(xì)介紹了WPF如何使用Accord實(shí)現(xiàn)屏幕錄制,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下2024-03-03C#通過創(chuàng)建Windows服務(wù)啟動(dòng)程序的方法詳解
這篇文章主要介紹了C#通過創(chuàng)建Windows服務(wù)啟動(dòng)程序的方法,較為詳細(xì)的分析了C#創(chuàng)建Windows服務(wù)應(yīng)用程序的步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-06-06C#使用AutoUpdater.NET實(shí)現(xiàn)程序自動(dòng)更新
開發(fā)桌面應(yīng)用程序的時(shí)候,經(jīng)常會(huì)因?yàn)樾略龉δ苄枨蠡蛐迯?fù)已知問題,要求客戶更新應(yīng)用程序,在.Net體系中采用?AutoUpdater.NET?組件可以非常便捷的實(shí)現(xiàn)這一功能,需要的朋友可以參考下2024-02-02