C# 中有三種定時(shí)器,System.Windows.Forms 中的定時(shí)器和 System.Timers.Timer
          的工作方式是完全一樣的,所以,這里我們僅討論System.Timers.Timer 和 System.Threading.Timer

          1、定時(shí)器?;?br>
          先來(lái)看一個(gè)例子:
          class Program { static void Main(string[] args) { Start(); GC.Collect();
          Read(); } static void Start() { Foo f = new Foo();
          System.Threading.Thread.Sleep(5_000); } } public class Foo {
          System.Timers.Timer _timer; public Foo() { _timer = new
          System.Timers.Timer(1000); _timer.Elapsed += timer_Elapsed; _timer.Start(); }
          private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
          WriteLine("System.Timers.Timer Elapsed."); } ~Foo() { WriteLine("---------- End
          ----------"); } }
          運(yùn)行結(jié)果如下:
          System.Timers.Timer Elapsed. System.Timers.Timer Elapsed. System.Timers.Timer
          Elapsed. System.Timers.Timer Elapsed. System.Timers.Timer Elapsed.
          System.Timers.Timer Elapsed. System.Timers.Timer Elapsed. ...
          在 Start 方法結(jié)束后,F(xiàn)oo 實(shí)例已經(jīng)失去了作用域,按理說(shuō)應(yīng)該被回收,但實(shí)際并沒(méi)有(因?yàn)槲鰳?gòu)函數(shù)沒(méi)有執(zhí)行,所以肯定實(shí)例未被回收)。

          這就是定時(shí)器的 ?;顧C(jī)制,因?yàn)槎〞r(shí)器需要執(zhí)行 timer_Elapsed 方法,而該方法屬于 Foo 實(shí)例,所以 Foo 實(shí)例被保活了。

          但多數(shù)時(shí)候這并不是我們想要的結(jié)果,這種結(jié)果導(dǎo)致的結(jié)果就是 內(nèi)存泄露,解決方案是:先將定時(shí)器 Dispose。
          public class Foo : IDisposable { ... public void Dispose() { _timer.Dispose();
          } }
          一個(gè)很好的準(zhǔn)則是:如果類中的任何字段所賦的對(duì)象實(shí)現(xiàn)了IDisposable 接口,那么該類也應(yīng)當(dāng)實(shí)現(xiàn) IDisposable 接口。

          在這個(gè)例子中,不止 Dispose 方法,Stop 方法和設(shè)置 AutoReset = false,都能起到釋放對(duì)象的目的。但是如果在 Stop
          方法之后又調(diào)用了Start 方法,那么對(duì)象依然會(huì)被?;睿幢?Stop 之后進(jìn)行強(qiáng)制垃圾回收,也無(wú)法回收對(duì)象。

          System.Timers.Timer 和 System.Threading.Timer 的保活機(jī)制是類似的。

          ?;顧C(jī)制是由于定時(shí)器引用了實(shí)例中的方法,那么,如果定時(shí)器不引用實(shí)例中的方法呢?

          2、不?;钕?System.Timers.Timer 和 System.Threading.Timer 的差異

          要消除定時(shí)器對(duì)實(shí)例方法的引用也很簡(jiǎn)單,將 timer_Elapsed 方法改成 靜態(tài) 的就好了。(靜態(tài)方法屬于類而非實(shí)例。)

          改成靜態(tài)方法后再次運(yùn)行示例,結(jié)果如下:
          System.Timers.Timer Elapsed. System.Timers.Timer Elapsed. System.Timers.Timer
          Elapsed. System.Timers.Timer Elapsed. ---------- End ----------
          System.Timers.Timer Elapsed. System.Timers.Timer Elapsed. System.Timers.Timer
          Elapsed. ...
          Foo 實(shí)例是被銷毀了(析構(gòu)函數(shù)已運(yùn)行,打印出了 End),但定時(shí)器還在執(zhí)行,這是為什么呢?

          這是因?yàn)椋?NET Framework 會(huì)確保 System.Timers.Timer 的存活,即便其所屬實(shí)例已經(jīng)被銷毀回收。

          如果改成 System.Threading.Timer,又會(huì)如何?
          class Program { static void Main(string[] args) { Start(); GC.Collect();
          Read(); } static void Start() { Foo2 f2 = new Foo2();
          System.Threading.Thread.Sleep(5_000); } } public class Foo2 {
          System.Threading.Timer _timer; public Foo2() { _timer = new
          System.Threading.Timer(timerTick, null, 0, 1000); } static void
          timerTick(object state) { WriteLine("System.Threading.Timer Elapsed."); }
          ~Foo2() { WriteLine("---------- End ----------"); } }
          注意,這里的 timerTick 方法是靜態(tài)的。運(yùn)行結(jié)果如下:
          System.Threading.Timer Elapsed. System.Threading.Timer Elapsed.
          System.Threading.Timer Elapsed. System.Threading.Timer Elapsed.
          System.Threading.Timer Elapsed. ---------- End ----------
          可見(jiàn),隨著 Foo2 實(shí)例銷毀,_timer 也自動(dòng)停止并銷毀了。

          這是因?yàn)椋?NET Framework 不會(huì)保存激活 System.Threading.Timer 的引用,而是直接引用回調(diào)委托。

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問(wèn)題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                人人干av| 人妻丰满熟妇av无码区波多野 | 国产免费无遮挡免费视频在线看 | 激情爱爱网址 | 能看的操逼网字吕 |