views:

804

answers:

7

Is there an advantage to dynamically attaching/detaching event handlers?

Would manually detaching handlers help ensure that there isn't a reference remaining to a disposed object?

A: 

Most of the the time the framwork takes care of that for you. Do you have an example of what you're trying to achieve?

jdecuyper
A: 

Manually detaching an event can be important to prevent memory leaks: the object that connects to an event fired by another object, will not be garbage collected until the object that fires the event is garbage collected. In other words, an "event-raiser" has a strong reference to all the "event-listeners" connected to it.

Tobi
A: 

I have an MDI Parent form that handles the events of a child form. When the child form is disposed, I need to make sure that the object gets garbage collected. It is possible that the form will be re-instantiated. When it is re-instantiated, will event handlers stack up and take up memory?

joek1975
In this case, when the child forms are no longer referenced, they will be garbage-collected. If, however, the child forms are handling events of the MDI parent, they will continue to exist until the parent is garbage-collected
rpetrich
+1  A: 

I find that dynamically attaching/detaching event handlers is only of use where you have a long-lived object exposes events that are consumed by many short-lived objects. For most other cases the two objects are disposed around the same time and the CLR does a sufficient job of cleaning up on its own

rpetrich
+2  A: 

I'm pretty sure that the Handles clause is just syntactic sugar and inserts an AddHandler statement into your constructor. I tested using this code and disabled the application framework so the constructor wouldn't have extra stuff:


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

The IL ended up like this:

  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

Notice two identical blocks of code around IL_000b and IL_0051. I think it's just syntactic sugar.

OwenP
could you just use the second quote in the comment for highlight `'... lots of lines here ADD > ` **`'`**
serhio
+2  A: 

It's not a question of using AddHandler versus Handles.

If you are concerned about the reference to your event handler interfering with garbage collection, you should use RemoveHandler, regardless of how the handler was attached. In the form or control's Dispose method, remove any handlers.

I have had situations in Windows Forms apps (.NET 1.1 days) where an event handler would be called on controls that had no other references to them (and which for all intents and purposes were dead and I would have thought been GC'ed) -- extremely hard to debug.

I would use RemoveHandler to get rid of handlers on controls that you are not going to reuse.

Pete
I think that I saw that in .Net 2.0 as well with a Timer object...
joek1975
Mmmm, are you sure that Handles does only add the AddHandler part? I thought that It did the RemoveHandler part too.
SoMoS
In newer versions of .NET, this might be smarter. In 1.1, this definitely happened!
Pete
+1  A: 

I manually attach handlers when I manually create controls (for example, dynamically creating a TextBox for each database record). I manually detach handlers when they are handling things I'm not quite ready to handle yet (possibly because I'm using the wrong events? :) )

CindyH
Thanks for the insight. I started to do this same process, and it is making my code cleaner as well as helping to understand the flow of the application.
joek1975