问题
I'm trying to understand how a Control
events are unsubscribed. Suppose I have a textbox and I have subscribed the TextChanged
event using the WinForms designer.
Is the TextChanged
event automatically unsubscribed in the Textbox
destructor, or must I explicitly unsunscribe to avoid memory leaks?
public void InitializeComponents()
{
...
this.emailTextBox.TextChanged += emailTextBox_TextChanged;
...
}
public override void Dispose()
{
if( disposing )
{
// DO I REALLY NEED THIS LINE?
this.emailTextBox.TextChanged -= emailTextBox_TextChanged;
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
回答1:
Any object which subscribes to events from a longer-lived object should implement IDisposable
and should unsubscribe those events when it is Dispose
d. Conceptually, there's no reason why objects shouldn't unsubscribe from all events when they are disposed, since doing so would avoid problems if an object whose events one subscribed turned out to live longer than expected. Unfortunately, the event architecture in .NET provides no mechanism for conveniently ensuring that events get cleaned up when objects are disposed, and having code unsubscribe a bunch of events when an object is disposed may make it harder to make sure that the few events which really need to be cleaned up are among the ones that are.
回答2:
In this situation I beleive it is OK not to unsubscribe because the TextBox to which you're subscribing is wholly contained within the parent control (or that's what I'm assuming.)
Therefore when no further references to the parent control exist, there won't be any external references to the TextBox and so both objects will become eligible for GC.
There are situations when you should unsubscribe from events to prevent memory leaks because the reference held by the event (in it's list of subscribers) is just the same as any other reference and would prevent the subscriber from being GC'd.
Such situations can occur when an object subscribes to an event on an external object (i.e. not owned by this object.) In this situation the subscriber would only become eligible for GC after the subscribed-to object was eligible for GC.
回答3:
The events are actually a list of event handlers (function delegates). So when you write this:
this.emailTextBox.TextChanged += emailTextBox_TextChanged;
You actually add your delegate emailTextBox_TextChanged
to the list of existing delegates associated to the TextChanged
event.
What this means is that when the textbox is disposed, this list will be disposed too, so you don't need to unsubscribe events in that case, and you won't have memory leaks.
So to answer your question, the event isn't really unsubscribed in the textbox destructor, but you don't need to do it explicitly.
The only case in which it will be useful to unsubscribe is when you don't want your function to handle the event anymore during execution, but I think I've never actually needed to do that.
回答4:
Yes, you better unsubscribe. As official docs say (here)
In order to prevent resource leaks, you should unsubscribe from events before you dispose of a subscriber object. Until you unsubscribe from an event, the multicast delegate that underlies the event in the publishing object has a reference to the delegate that encapsulates the subscriber's event handler. As long as the publishing object holds that reference, garbage collection will not delete your subscriber object.
来源:https://stackoverflow.com/questions/17108217/do-i-need-to-unsubscribe-events-in-my-form