欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# 定時(shí)器?;顧C(jī)制引起的內(nèi)存泄露問(wèn)題解決

 更新時(shí)間:2020年02月12日 11:32:52   作者:丹楓無(wú)跡  
這篇文章主要介紹了C# 定時(shí)器保活機(jī)制引起的內(nèi)存泄露問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

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

1、定時(shí)器保活

先來(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)則是:如果類(lèi)中的任何字段所賦的對(duì)象實(shí)現(xiàn)了IDisposable 接口,那么該類(lèi)也應(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 的?;顧C(jī)制是類(lèi)似的。

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

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

要消除定時(shí)器對(duì)實(shí)例方法的引用也很簡(jiǎn)單,將 timer_Elapsed 方法改成 靜態(tài) 的就好了。(靜態(tài)方法屬于類(lè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í)例是被銷(xiāo)毀了(析構(gòu)函數(shù)已運(yùn)行,打印出了 End),但定時(shí)器還在執(zhí)行,這是為什么呢?

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

如果改成 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í)例銷(xiāo)毀,_timer 也自動(dòng)停止并銷(xiāo)毀了。

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Unity使用攝像機(jī)實(shí)現(xiàn)望遠(yuǎn)鏡效果

    Unity使用攝像機(jī)實(shí)現(xiàn)望遠(yuǎn)鏡效果

    這篇文章主要為大家詳細(xì)介紹了Unity攝使用像機(jī)實(shí)現(xiàn)望遠(yuǎn)鏡效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • C#實(shí)現(xiàn)在啟動(dòng)目錄創(chuàng)建快捷方式的方法

    C#實(shí)現(xiàn)在啟動(dòng)目錄創(chuàng)建快捷方式的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)在啟動(dòng)目錄創(chuàng)建快捷方式的方法,涉及C#快捷方式的創(chuàng)建技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • C#窗體間常用的幾種傳值方式及委托與事件詳解

    C#窗體間常用的幾種傳值方式及委托與事件詳解

    這篇文章主要給大家介紹了關(guān)于C#窗體間常用的幾種傳值方式及委托與事件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用小程序具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • C# Mqtt 斷線(xiàn)重連的實(shí)現(xiàn)代碼

    C# Mqtt 斷線(xiàn)重連的實(shí)現(xiàn)代碼

    這篇文章主要介紹了C# Mqtt 斷線(xiàn)重連,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • C#7.0中新特性匯總

    C#7.0中新特性匯總

    C#7.0 增加了許多新功能,并專(zhuān)注于數(shù)據(jù)消費(fèi),簡(jiǎn)化代碼和性能的改善。接下來(lái)通過(guò)本文給大家介紹C#7.0中新特性匯總,需要的朋友可以參考下
    2016-08-08
  • c#并行任務(wù)多種優(yōu)化方案分享(異步委托)

    c#并行任務(wù)多種優(yōu)化方案分享(異步委托)

    c#并行任務(wù)多種優(yōu)化方案分享,使用異步委托+回調(diào)函數(shù)方式實(shí)現(xiàn),大家參考使用吧
    2013-12-12
  • Unity UGUI通過(guò)搖桿控制角色移動(dòng)

    Unity UGUI通過(guò)搖桿控制角色移動(dòng)

    這篇文章主要為大家詳細(xì)介紹了Unity3D基于陀螺儀實(shí)現(xiàn)VR相機(jī)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Unity3D實(shí)現(xiàn)扭動(dòng)擠壓瀏覽效果

    Unity3D實(shí)現(xiàn)扭動(dòng)擠壓瀏覽效果

    這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)扭動(dòng)擠壓瀏覽效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C# 操作Excel代碼總結(jié)

    C# 操作Excel代碼總結(jié)

    這篇文章主要介紹了C# 操作Excel代碼總結(jié),具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • C#?將Excel轉(zhuǎn)為PDF時(shí)自定義表格紙張大小的代碼思路

    C#?將Excel轉(zhuǎn)為PDF時(shí)自定義表格紙張大小的代碼思路

    這篇文章主要介紹了C#?將Excel轉(zhuǎn)為PDF時(shí)自定義表格紙張大小的代碼思路,轉(zhuǎn)換前的頁(yè)面大小設(shè)置為該版本中寫(xiě)入的新功能,在舊版本和免費(fèi)版本中暫不支持,感興趣的朋友跟隨小編一起看看實(shí)例代碼
    2021-11-11

最新評(píng)論