Question Add/RemoveHandler

ALX

Well-known member
Joined
Nov 16, 2005
Messages
253
Location
Columbia, SC
Programming Experience
10+
Recently I noticed something strange going on in VS due to some sloppy programming on my part. An event being raised from one form was being handled in another form, which is what it typically SHOULD be doing, except that the form doing the handling had been closed and disposed. 'No errors like "trying to access a disposed object" or anything like that. In fact the handler executed perfectly as if the disposed form was still active. This got me thinking, (I know that's dangerous), that there could be many event handlers taking up valuable space in VS's memory that should have been long since trashed. It also got me thinking about the cases where I've used the "AddHandler" statement and not been in a position to remove all of those handlers at the closing of a form. My question is: If I don't specifically "Remove" any handlers that I've added at run time, will those handlers be lingering, or taking up resources after the handling forms have closed?
 
The object will not be released from memory until you call RemoveHandler, so you must make sure you do that.
Sometimes using a WithEvents variable is more convenient since it can simply be reassigned or dereferenced to break the event handler reference.
 
Actually, in this particular case, I was using a "WithEvents" statement. I've prepared a small example. Form1 has 3 buttons & looks like....
VB.NET:
Public Class Form1

    Dim Frm2 As Form
    Event CallForm2Sub()


    Private Sub OpenForm2(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles Button1.Click

        Frm2 = New Form2(Me)
        Frm2.Location = New Point(Me.Location.X + Me.Width, Me.Location.Y)
        Frm2.Show()
    End Sub

    Private Sub CloseForm2(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles Button2.Click

        Frm2.Close()
        Frm2.Dispose()
    End Sub

    Private Sub RaiseEvent1(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles Button3.Click

        RaiseEvent CallForm2Sub()
    End Sub
End Class

Form2 looks like...
VB.NET:
Public Class Form2

    Friend WithEvents Frm As Form1

    Public Sub New(ByVal Frm As Form1)
        InitializeComponent()
        Me.Frm = Frm
    End Sub

    Friend Sub Sub2() Handles Frm.CallForm2Sub

        MessageBox.Show("This handler is called after this Form has been disposed.")

    End Sub
End Class

Start by creating Form2 (Button1)... then close it (Button2)... then raise the event (Button3).
I'm not sure how I could "Remove" the event handler in this case...?
 
Last edited:
Are you sure the form has no events that would give you this information? :) Form Events (System.Windows.Forms)
When it is time you simply set the WithEvents variable holding the form reference to Nothing.
 
So in Form2 FormClosing, I should add Frm = Nothing....? That's simple! Thank You...
I may still be in trouble because I don't know if I can recreate a record of all the events being assigned as they are generated within a constantly changing layout. I did search previously for "Remove Handlers" and got nothing but C# code, which is close to Greek for me. Nothing for VB... I did notice one quote in another forum (which was related to C#)... and I'm wondering if it applies here.
"It's the object which publishes the events which keeps the targets of the event handlers live."
This makes me think that when the form class that assigns the handler goes out of scope, that the associated handler procedure would also be eligible for Garbage Collection... and makes me think that these handlers would eventually be cleaned up... rather than creating memory leaks in the long haul... Is there any valid logic here?
 
Last edited:
I need to follow up here, because our readers really enjoy stupid questions. After my last post, the first thing I did was to search through my entire project for all occurrences of the phrase "WithEvents" to find any instances were I might be leaving event handlers lingering after the associated classes have been disposed. Of course what I found are the hundreds of WithEvents statements that were created by the " Windows Form Designer generated code ". It appears to me that these statements are identical to the "WithEvents" statements that I have added in the declarations portions of these form classes. I'm guessing that the way .NET keeps track of which events to kill is because the Designer generated entries are in the section "Private components As System.ComponentModel.IContainer"... and uses that list when executing "components.Dispose()". Is that even close to correct? 'And a really stupid follow up question: If that's the case, couldn't I put all of my WithEvents statements in with the Designer generated statements so they get disposed with everything else?
 
You don't put anything in designer generated code directly, that area is reserved and regenerated everytime you make a change in designer.

Components (Container actually) is one of the things designer puts there if you add any component (not control) to the form, and as part of the disposing of the form is adds code (overrides Dispose method) to also dispose that container and its content. If you add a control the generated code adds it to a Controls collection. All these controls/components are assigned a WithEvents variable for easy event handling of all their events from designer or code editor.

The form itself implements IDisposable where it disposes all controls in Controls collection, this is part of the Form class definition and not something you can read anywhere in project code. A modeless form is disposed when it is closed, a modal form when the caller calls Dispose method. To add custom cleanup you can override Dispose method or handle the Disposed event. Controls added to a form is not necessary to dispose, because as explained these are taken care of by the form when that disposes.
 
Back
Top