C 定時器保活機制引起的記憶體洩露問題

2022-01-09 21:46:12 字數 2824 閱讀 5285

c# 中有三種定時器,system.windows.forms中的定時器和system.timers.timer的工作方式是完全一樣的,所以,這裡我們僅討論system.timers.timersystem.threading.timer

先來看乙個例子:

class program

static void start()

}public class foo

private void timer_elapsed(object sender, system.timers.elapsedeventargs e)

~foo()

}

執行結果如下:

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方法結束後,foo例項已經失去了作用域,按理說應該被**,但實際並沒有(因為析構函式沒有執行,所以肯定例項未被**)。

這就是定時器的保活機制,因為定時器需要執行timer_elapsed方法,而該方法屬於foo例項,所以foo例項被保活了。

但多數時候這並不是我們想要的結果,這種結果導致的結果就是記憶體洩露,解決方案是:先將定時器dispose

public class foo : idisposable

}

乙個很好的準則是:如果類中的任何欄位所賦的物件實現了idisposable介面,那麼該類也應當實現idisposable介面。

在這個例子中,不止dispose方法,stop方法和設定autoreset = false,都能起到釋放物件的目的。但是如果在stop方法之後又呼叫了start方法,那麼物件依然會被保活,即便stop之後進行強制垃圾**,也無法**物件。

system.timers.timersystem.threading.timer的保活機制是類似的。

保活機制是由於定時器引用了例項中的方法,那麼,如果定時器不引用例項中的方法呢?

要消除定時器對例項方法的引用也很簡單,將timer_elapsed方法改成靜態的就好了。(靜態方法屬於類而非例項。)

改成靜態方法後再次執行示例,結果如下:

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例項是被銷毀了(析構函式已執行,列印出了 end),但定時器還在執行,這是為什麼呢?

這是因為,.net framework 會確保system.timers.timer的存活,即便其所屬例項已經被銷毀**。

如果改成system.threading.timer,又會如何?

class program

static void start()

}public class foo2

static void timertick(object state)

~foo2()

}

注意,這裡的timertick方法是靜態的。執行結果如下:

system.threading.timer elapsed.

system.threading.timer elapsed.

system.threading.timer elapsed.

system.threading.timer elapsed.

system.threading.timer elapsed.

---------- end ----------

可見,隨著foo2例項銷毀,_timer也自動停止並銷毀了。

這是因為,.net framework 不會儲存啟用system.threading.timer的引用,而是直接引用**委託。

C 定時器保活機制引起的記憶體洩露問題解決

c 中有三種定時器,system.windows.forms 中的定時器和 system.timers.timer 的工作方式是完全一樣的,所以,這裡我們僅討論 system.timers.timer 和 system.threading.timer 1 定時器保活 先來看乙個例子 class pr...

TCP保活定時器

tcp有keepalive功能,它和http的keepalive功能目的不一樣。tcp伺服器希望知道客戶端是否崩潰 重新啟動或者中間路由不通。保活定時器就提供這種功能。在進一步介紹tcp的保活定時器前,先了解乙個概念 長連線和短連線。tcp是長連線 長連線 建立乙個連線,多個請求復用這個連線,最後再...

(23)TCP的保活定時器

一 簡介 對於運輸層是否應該存在保活定時器的討論一直都有,一些專家覺得這應該有應用層自行維護。如果乙個給定的連線在2小時內沒有任何動作,那麼伺服器就向客戶傳送乙個探查報文段。客戶主機必須處於以下4個狀態之一。1 客戶主機依然正常執行,並從伺服器可達。客戶的tcp響應正常,而伺服器也知道對方的正常工作...