2012-12-11 99 views
1

我有一個程序集拖動了一個COM Interop VB 6.0文本編輯器,並將它用作一個.NET包裝的控件... 然後在一個新的程序集是一個Windows窗體,我拖放上面的程序集,開始使用它,聲明它的一個變量,並且如果Assmbley abvoe被namved MyTextControl則在該窗口形成我有mytxtcntrl爲它像Form_Closed是刪除事件處理程序的正確位置嗎?

mytxtcntrl.TextEditor.ObjectDblClicked += new AxTextEditorLib._DTextEditorEvents_ObjectDblClickedEventHandler(ctlTEEditor_ObjectDblClicked); 
可變和一些事件處理程序分配事件處理它,因此例如

因此,現在Sholud我甚至擔心用「 - =」去除這些事件處理程序?或GC會照顧它? 如果我應該手動進行,那麼正確的位置是什麼?我把它們放在Form_Closed部分並運行內存分析器,它沒有任何影響。

+1

我有一段時間沒有在.NET中處理過ActiveX控件,但是在.NET中曾經存在過一個錯誤,它在窗體被關閉和處置後不能幹淨地擺脫ActiveX控件,所以它很可能取消訂閱是一個好主意。取消訂閱關閉或覆蓋表單的Dispose(布爾)應該沒問題。 – Pete

回答

2

不,你不應該。 GC會照顧它。唯一需要擔心「丟掉」物體的地方是當你使用一個實現IDisposable的類或者當你正在做System.Runtime.InteropServices的時候。

+0

這不完全正確,.NET中內存泄漏的主要原因之一是事件處理程序未被註冊。 –

+0

「當你使用一個實現IDisposable的類時」好吧,我也有這些,我的一個類正在實現IDisposable,並且它有一個textEditor類型的變量。在那種情況下,移除事件處理程序的正確位置是哪裏? – Bohn

+0

@TrevorPilley有趣的是,你有這方面的任何來源? – antonijn

3

僅當事件源對象超出事件訂閱者時才需要顯式取消訂閱事件。不這樣做會保留對訂閱對象的引用,防止它們被垃圾收集。

WinForms非常精心設計,以避免這種事故。您通常會在窗體或用戶控件中編寫一個事件處理函數來監聽由子控件觸發的事件。這些子控件的生命週期與表單的生命週期密切相關,它們在用戶關閉表單時同時處理。垃圾收集器不會被這個難倒,並在同一時間收集它們。

您的ActiveX控件適合這種模式,它將成爲您的窗體的子控件,因此在模板完全同時死亡時會死掉。根本不需要顯式清理。

有一些角落情況下,這不會像描述的那樣工作。傳統的方法是在自己的代碼中自己移除控件,但保持表單活着。現在您應該取消訂閱任何事件以允許該控件被垃圾收集。最重要的是,您還必須在控件上顯式調用Dispose()以確保它的本機窗口被銷燬。如果不這樣做會產生永久性泄漏,即使垃圾收集器無法解決,控件也會通過窗口句柄保持活動狀態。

第二種情況是SystemEvents類。它的事件是靜態的,類對象將一直存在,直到程序終止。您必須明確退訂其事件,如果您使用它們的形式可能會被關閉而沒有終止應用程序。

相關問題