Event unsubscription

J

joe

Hi,
I am sorry to ask similar questions again, but I could not
find answers anywhere. My question is this:
Why, even after calling Dispose on a control, which has
subscribed for timer events, the control still receive
events? The only way to fix the problem is to unsubscribe
from the Tick event in the control's Disposed event.

class MyForm:public Form
{
MyUserControl myControl;
public System.Windows.Timer Timer t=new Timer();
Foo()
{
if (myControl!=null) myControl.Dispose();
myControl=new MyUserControl();
}
}
class MyUserControl:...
{
MyUserControl()
{
MyForm.t.Tick+=Timer_Tick(...)
}
Timer_Tick(...)
{// gets fired even for non-existing
//controls
}
}
// somewhere in the code call Foo twice

Foo();
..........
Foo();

Now the timer event will be fired twice-for the control
that is currently assigned to myControl and for the old
control. Why does this happen for the old one? After
assigning a new instance to myControl the old one should
be GC (or become eligible for it), particularly after
calling Dispose on it. Even if it is not CG, why should it
get events? After all, if no references to it exist, this
is a mark that no one is interested in the control, let
alone the events it had subscriptions for.

Thanks,
joe
 
C

Codemonkey

Joe,

Even after calling Dispose, the instance of your control still lives in
memory until the Garbage collector comes along and destroys it (when it
actually does this is depends on various factors - system memory usage,
generation of the object etc). Because the instance is still alive, it can
still receive events as normal.

The reason for the Dispose method is to release Unmanaged resources such as
files, COM ports or Window handles. You should do any termination code in
the Dispose Method (including removing Event handlers etc).
After all, if no references to it exist, this
is a mark that no one is interested in the control, let
alone the events it had subscriptions for.


As far as I know, event handlers are implemented using delegates in .net -
this means that the event itself still has a reference to your object even
after it has been disposed. I don't think the GC recognizes this as a reason
to keep the object from being Finalized though. As a result, your object is
called by the event up until the point it is finalized. (Please correct me
anyone if I'm wrong on this point)

My advice is to do a proper cleanup code in the Dispose Method. You could
also check the IsDisposed property on the control before doing any
processing in the event handlers.

Hope this Helps,

Trev.
 
J

joe

I undesrtand that objects dont get destroyed immediately.
But for the developer this should be transparent-once you
are finished with the object, you deem it dead, it is just
a matter of time to get destroyed. It is confusing that in
my code I dont reference an object anymore (which means I
am not interested in it), yet I get notified.
The other point is that even if I dont hold any unmanaged
resources in my control class, I have to call Dispose(),
which in turn will fire the Disposed event, in which
handler I have to unsubscribe from the events I dont want.

Thanks,

joe
 
C

Codemonkey

Joe,
I undesrtand that objects dont get destroyed immediately.
But for the developer this should be transparent-once you
are finished with the object, you deem it dead, it is just
a matter of time to get destroyed.

Not in all cases. Some developers implement object pooling based on the fact
that you can ressurrect objects before the Garbage Collector comes along.
I have to call Dispose(),
which in turn will fire the Disposed event, in which
handler I have to unsubscribe from the events I dont want.

If the events are coming from a Windows Form's timer or other control on the
form being disposed, then you shouldn't have to unregister the event
handlers as the controls themselves should be disposed and stop raising
their events. However, if the events come from another object hosted outside
the form then you *should* unregister event handlers when the form is being
disposed.

Hope this helps,

Trev.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top