2008-09-11 68 views
1

動態連接/分離事件處理程序是否有優勢?Handles vs. AddHandler

手動分離處理程序是否有助於確保沒有對處置對象的引用?

回答

2

這不是使用AddHandler與Handles的問題。

如果您擔心引用您的事件處理程序干擾垃圾回收,則應使用RemoveHandler,而不管處理程序是如何連接的。在窗體或控件的Dispose方法中,刪除所有處理程序。

我在Windows Forms應用程序(.NET 1.1天)中遇到了一些情況,事件處理程序將在沒有其他引用的情況下調用事件處理程序(對於所有意圖和目的, GC'ed) - 非常難以調試。

我會使用RemoveHandler來擺脫您不打算重用的控件的處理程序。

0

大多數情況下,框架爲您提供幫助。

0

手動分離事件對於防止內存泄漏非常重要:連接到由另一個對象觸發的事件的對象將不會被垃圾收集,直到觸發事件的對象被垃圾收集爲止。換句話說,「事件提升者」對所有與之相關的「事件監聽者」有很強的參考價值。

1

我發現動態連接/分離事件處理程序僅用於擁有長壽命對象的情況下公開許多短暫對象所使用的事件。對於大多數其他情況下,兩個對象大約在同一時間處理,並且CLR有足夠的自己清理工作

3

我很肯定Handles子句只是語法糖,並將AddHandler語句插入到您的構造函數。我測試了使用此代碼和殘疾人的應用程序框架,這樣的構造不會有多餘的東西:


Public Class Form1 

    Public Sub New() 
     ' This call is required by the Windows Form Designer. ' 
     InitializeComponent() 

     ' Add any initialization after the InitializeComponent() call. ' 
     AddHandler Me.Load, AddressOf Form1_Load 
    End Sub 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     Dim breakpoint As Integer = 4 
    End Sub 
End Class

的IL弄成這個樣子:

IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: call  instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor() 
    IL_0007: nop 
    IL_0008: ldarg.0 
    IL_0009: ldarg.0 
    IL_000a: dup 
    IL_000b: ldvirtftn instance void WindowsApplication1.Form1::Form1_Load(object, 
                      class [mscorlib]System.EventArgs) 
    IL_0011: newobj  instance void [mscorlib]System.EventHandler::.ctor(object, 
                      native int) 
    IL_0016: call  instance void [System.Windows.Forms]System.Windows.Forms.Form::add_Load(class [mscorlib]System.EventHandler) 

'... lots of lines here ' 

    IL_0047: ldarg.0 
    IL_0048: callvirt instance void WindowsApplication1.Form1::InitializeComponent() 
    IL_004d: nop 
    IL_004e: ldarg.0 
    IL_004f: ldarg.0 
    IL_0050: dup 
    IL_0051: ldvirtftn instance void WindowsApplication1.Form1::Form1_Load(object, 
                      class [mscorlib]System.EventArgs) 
    IL_0057: newobj  instance void [mscorlib]System.EventHandler::.ctor(object, 
                      native int) 
    IL_005c: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Form::add_Load(class [mscorlib]System.EventHandler) 
    IL_0061: nop 
    IL_0062: nop 
    IL_0063: ret 
} // end of method Form1::.ctor

注意兩個代碼相同的塊左右IL_000b和IL_0051。我認爲這只是句法糖。

1

我手動創建控件(例如,爲每個數據庫記錄動態創建TextBox)時手動附加處理程序。我手動分離處理程序時,他們正在處理的事情,我還沒有準備好處理(可能是因爲我使用錯誤的事件?:))

1

聲明字段爲WithEvents將導致編譯器自動生成一個屬性用那個名字。 getter返回後臺字段的值。制定者稍微複雜一點。它首先檢查後臺字段是否已經具有正確的值。如果是這樣,它就退出。否則,如果後備字段非空,它會將其所有事件的「RemoveHandler」請求發送到由後臺字段標識的對象。接下來,無論支持字段是否爲非空值,它都會將其設置爲等於所請求的值。最後,如果新值是非空值,那麼無論舊值是否爲新值,屬性都會將其所有事件的「AddHandler」請求發送到由新值標識的對象。

假設在丟棄它之前將對象的所有WithEvents成員設置爲Nothing,並且避免在多個線程中操作WithEvents成員,自動生成的事件代碼將不會泄漏。