2

I am working on a C# application that has multiple forms.
When I open one of the forms I add an event listener like this: SomeClass.MotionCompleted += new EventHandler(HandlerMethod); . The MotionCompleted event is a static event.

I have noticed that after closing this form the HandlerMethod still gets called when the event occurs which then causes an exception because it tries to update something on the form which doesn't exist anymore.

How can the event listener exist and respond to the event even though the form doesn't exist anymore? Once form.Close() or this.Close() is called shouldn't that automatically unhook the event listeners so that they do not get called anymore?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
PICyourBrain
  • 9,976
  • 26
  • 91
  • 136

9 Answers9

7

That's the evil of static events! :) You have a managed leak there.

Override the OnClosing of your form and deregister you handler:

protected override void OnClosing(CancelEventArgs e) {
    SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
}
Community
  • 1
  • 1
Stormenet
  • 25,926
  • 9
  • 53
  • 65
  • I figured this was the answer I was just hoping there was a way for it to be done automatically! – PICyourBrain Nov 05 '10 at 14:07
  • You should do some reading on the .net garbage collector. Because the event is static it is an "root" object an contains a handler with a reference to your form. Because of that reference your form stays alive even when you think it isn't. – Stormenet Nov 05 '10 at 14:12
  • 3
    OnFormClosing is not technically correct, it might be canceled. Use OnFormClosed. Cutting and pasting the Dispose() method from the designer file is even more correct. This is as automatic as its going to get. – Hans Passant Nov 05 '10 at 16:23
  • @hans +1, however, OnClosing leaves some potential future fun for the user and thus better understanding of how .net wrapped winforms work. – Stormenet Nov 06 '10 at 01:57
2
Someclass.MotionCompleted -= new EventHandler(HandlerMethod);

This article shows a lot of tips regarding events in C#:
https://csharpindepth.com/articles/Events

N3pp
  • 33
  • 1
  • 4
Greg
  • 21,235
  • 17
  • 84
  • 107
1

To add to all the duplicate answers you can also unhook this way:

SomeClass.MotionCompleted -= HandlerMethod;

The output assembly code will be the same whether you use -= HandlerMethod or -= new EventHandler(HandlerMethod).

Jla
  • 11,304
  • 14
  • 61
  • 84
0
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);

just change the "+" to "-"

Arief
  • 6,055
  • 7
  • 37
  • 41
0

You have to unhook in manually:

SomeClass.MotionCompleted -= HandlerMethod;
Brad Rem
  • 6,036
  • 2
  • 25
  • 50
vaitrafra
  • 666
  • 3
  • 15
0

You can use this sample of code :

SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);

However, you must be careful to unhook your event from the same instance of the object containing HandlerMethod that the one which registered it.

Thibault Falise
  • 5,795
  • 2
  • 29
  • 32
0

You need to manually unhook the event like this: SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);

Mike Dour
  • 3,616
  • 2
  • 22
  • 24
0

Not exactly. The form is not collected by the garbage collector because the event handler is still there. The static event handlers don't get unhooked by themselves. You can unhook any assigned event in the form onClosing method like:

SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);

After that everything should work.

Adrian Fâciu
  • 12,414
  • 3
  • 53
  • 68
0

Events are strong reference : they cannot be garbage collected unless you explicitely dereferece them.

That's why I suggest youw rite a subscribe and an unsubscibe methods that will do their jobs and centralize this hooks (which will results in memory leaks if you don't free them)

private void subscribeAll()
{
  SomeClass.MotionCompleted += new EventHandler(HandlerMethod);
  // other subscription
}

private void unSubscribeAll()
{
  SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
  // other subscription
}
Benjamin Baumann
  • 4,035
  • 2
  • 25
  • 35