2010-02-05 80 views
5

我分析了一個VB.NET項目,並且有一些對象(孩子MDI窗體)被處置,但未被GC刪除。事件處理程序和內存泄漏

的MemoryProfiler分析發現,除其他外,以下內容:

「這個實例配置,仍然 間接的事件處理程序紮根 這通常表明 事件處理程序一直沒有得到妥善 刪除,是的 內存泄漏的常見原因。下面的實例是 的事件處理程序(一個或多個)直接紮根。 調查他們獲得有關此問題的詳細信息 ......」

現在,我試圖弄清楚這意味着什麼以及如何解決它。

我有一個MDI表單和一個子表單。兒童表格在打開/關閉後未被GC收集,顯然是因爲MDIForm參考的仍然是(間接的)EventHandlerList ...

什麼是它,我該如何解決它?

我試着在this thread建議修復,因爲曾與在PropertyStore,現在MDI參考該淘汰了問題,但出現了MDI EventHandlerList參考子窗體...

後一些代碼分析我觀察到一些

AddHandler newMenu.Click, AddressOf ClickMenu 

沒有在前RemoveHandler newMenu.Click, AddressOf ClickMenu。它可能是主要原因嗎?

而且,一propos,是Handles

Private Sub ClickMenu(sender as Object, e as EventArgs) Handles newMenu.Click 

更好的是

RemoveHandler newMenu.Click, AddressOf ClickMenu 
AddHandler newMenu.Click, AddressOf ClickMenu 

但從內存分配點?

+0

剪去代碼可能會有所幫助。特別是添加和刪除事件處理程序並處理代碼。 – 2010-02-05 13:43:57

+0

在處理後調用GC.Collect()有什麼區別嗎?僅僅因爲某些東西被處置並不總是意味着它被垃圾直接收集起來。 – Ian 2010-02-05 13:45:03

+0

另外..這真的是一個問題?通過閱讀您關聯的論壇可以發現,隨着時間的推移,這種情況不會變得更糟。通過MS代碼泄漏幾kb將會產生巨大影響? – Ian 2010-02-05 13:46:57

回答

4

EventHandlerList被類使用,它提供大量的事件,以便在需要時爲事件支持字段分配空間,而不是在事件聲明時爲其更高效地處理內存。主窗體的所有事件都存儲在那裏。

我希望子窗體可以在其父項可以關閉時進行監視(這是一種常見用例),並且在收到該事件時不會退訂FormClosingFormClosed事件。但是,這只是一個猜測。爲了確認,請查看您的子表單實現,並查找它從父表單訂閱事件的所有情況,然後確保這些事件有相應的取消訂閱。

更新
你發現沒有被去除很可能是你看到問題的根源的菜單句柄。嘗試添加刪除呼叫,看看是否解決泄漏。

2

還有另一個對象引用GC應該通過事件處理程序刪除的對象。含義:還有另一個對象仍然訂閱了處置對象的事件。

當您想要處理該對象時,您可以通過取消訂閱事件(從事件中刪除事件處理程序)來解決此問題。