Remove event listener from local variable - c#

Do I have to worry about removing event listeners assigned to local variables?
Consider the following sample:
var zipUtil = new ZipUtil();
zipUtil.ProgressChanged += ZipUtil_ProgressChanged;
I'm creating an instance of the ZipUtil class which is stored as a local variable within a method. Do I have to remove the listener (zipUtil.ProgressChanged -= ZipUtil_ProgressChanged;) before the method terminates or is it okay to skip the step?

No, you don't have to remove that event handling method.
When adding an event handler to an event, a reference from the (object containing the) event to the event handler is created, not the other way round. Once zipUtil goes out of scope, the event handler will not make any difference pertaining to references to zipUtil.

Two lines of code are never enough to make the call accurately. But it is very unlikely you'll need to unsubscribe explicitly. There are two possible problem scenarios:
the class may fire its event at an inopportune time, after your object is disposed for example. That's fairly unlikely in this scenario, surely the ZipUtil class stops raising ProgressChanged events when you stop calling its methods. Not completely out of the question, it could do work on a background thread for example. Not visible from your snippet.
you can have a garbage collection problem due to events. The event delegate keeps an implicit reference to your class object, necessary so it can call ZipUtil_ProgressChanged() method. If it is an instance method, not clear from your snippet. That reference will keep your outer class alive. But not the other way around. Given that the lifetime of the ZipUtil object is restricted to the method and you surely want your outer class to survive at least to the end of the method, this should never be a problem.
High odds that ZipUtil implements IDisposable btw. Do make sure you use the using statement if it does.

Related

Anonymous method for event handler not a leak?

Whenever you add a delegate to an event handler, you should remove it later, right? So if you attach an anonymous method to an event, does this create an event handler leak since you can't later remove it? This code sample from http://msdn.microsoft.com/en-us/library/0yw3tz5k%28VS.80%29.aspx seems to imply that this an okay practice though.
// Create a handler for a click event
button1.Click += delegate(System.Object o, System.EventArgs e)
{ System.Windows.Forms.MessageBox.Show("Click!"); };
Is this really an okay practice?
Whenever you add a delegate to an event handler, you should remove it later, right?
Not necessarily, no. Often you want the event handler to stay valid for as long as the event itself can be raised - that's certainly very common with UIs.
Is this really an okay practice?
Absolutely, so long as you don't need to unhook the handler. Think about the point at which you'd unhook the event handler. If it's "when the form (or button, or whatever) is elegible for garbage collection" then what benefit is there in removing the handler? Just let it be garbage collected with the form...
Whenever you add a delegate to an event handler, you should remove it later, right?
Well, not always. There are two reasons why you'd want to remove an event handler that you're adding:
You're constantly adding handlers to the same instance that are short lived. If you didn't remove them then there would be more and more handlers added, when most of them aren't needed.
Your handler internally holds onto a reference to an object who's lifetime is much shorter than the lifetime of whatever object the event belongs to, and the event handler won't be (or can't be) called once that other object goes out of scope. Leaving the event handler attached will either force it to stay in memory longer than desired, or possibly result in using an object that's "stale" and shouldn't be used anymore. (For example, if the resource has already been disposed you don't want that event to fire anymore.)
The reason #2 is an issue is because of how Garbage Collection works in C#. It marks all objects that it can be 100% sure are in scope as "alive", and then follows everything that any of those "alive" objects reference as also being "alive" until it's followed every reference in every live object. Anything that was never marked as "alive" is then deemded "dead" and eligible for garbage collection.
When you have an event handler attached to an event that delegate contains two things, an instance of an object and a method to run on that object. That referenced object won't be able to be garbage collected until either:
The object with the event is no longer "alive".
You remove the event handler (i.e. the reference to) your delegate, allowing your object to be freed earlier.
That said, a significant percentage of cases don't apply to either of those, so there's no need to bother removing the event handlers.
As an example, I often see people removing event handlers just before the event object goes out of scope. That's pointless. If the object is out of scope there's no problem with it holding onto references to...whatever.
Now, if you are in one of those few situations in which you do need to unsubscribe the event handler, and you're using an anonymous method you need to...not. Just create a class that can make it a named method and use that.
Subscibing to event with anonymous method (or lambda expression) potentially can lead to memory leaks, but not in this case.
In this case compiler will generate an anonymous method inside current class and you don't have any memory related issues as long as your button will not live much longer than your object.
The use of inline anonymous delegates as event handlers does prevent those handlers being removed, as you stated. This can indeed cause problems, especially if the delegate comes from a different object. If you had a class A with a public event E, and E was subscribed to by a class B (that has no containing/contains relationship to A) attaching an anonymous handler H, H is technically a member of B, and so as long as it's referred to (by being attached to A's event), B won't be GCed. B's lifetime becomes tied to A's, and if you didn't want or expect that you now have a memory leak.
Now, that's not always a problem. If B contains A, or the other way around, then A and B's lifetimes are already tied together anyway; in your case, the button itself will very probably be disposed of before its containing control that attached the handler. Similarly, A and B could be long-lived objects (say, the program's main form and a data repository) and won't be GCed until the program terminates anyway. As long as you never have to care about a difference in lifetime between A and B, and you never need to detach H from E to stop exhibiting whatever behavior H has, then you can attach all the anonymous handlers you like.

Is there a reason to remove a method from an event after it has been invoked in Silverlight?

Recently I have come across an increasing number of people who have code similar to the following:
private AsynchronousReader r;
public SynchronousReader()
{
r = new AsynchronousReader();
// My practice is to put this here
// and then never remove it and never add it again
// thus cleaning up the code and preventing constant add/remove.
//r.ReadCompleted += this.ReadCompletedCallback;
}
private ReadCompletedCallback()
{
// Remove the callback to "clean things up"...
r.ReadCompleted -= this.ReadCompletedCallback;
// Do other things
}
public Read()
{
r.ReadCompleted += this.ReadCompletedCallback;
// This call completes asynchronously and later invokes the above event
r.ReadAsync();
r.WaitForCompletion();
}
Folks say that this practice is better than the one I indicated above and have given several reasons specific to Silverlight. They state it prevents memory leaks, threading issues, and even that it is the normal practice.
I have not done much Silverlight, but it seems silly to do this still.
Are there any specific reasons one would use this method instead of just rigging up the callback in the constructor once and for the lifetime of the object?
This is as simple as I could make my example. Ignore the fact that it's a sort of wrapper that turns an asynchronous object into a synchronous one. I'm only curious about the way events are added and removed.
In the case you mention it would make sense to hook it up once, but potentially the objects (parent and/or child) may not get garbage collected as the event handlers still reference them.
According to Marc Gavel here
i.e. if we have:
publisher.SomeEvent += target.SomeHandler;
then "publisher" will keep "target" alive, but "target" will not keep
"publisher" alive.
A more important point to bear in mind might be the lifespan of the child object. If it is the same as the parent, then one-off subscription in the constructor makes more sense. If it is dynamic you will likely want to remove the handlers as I have seen them leak (resulting in multiple callbacks).
Note: If the constructor-only method turns out to leak objects, you can always put an unsubscribe in the Dispose() I guess, but I can't say I have ever seen that.
It sounds like you have two issues:
You're attempting to reuse an object that really should only be used once.
That object needs to get properly cleaned up.
You should really either only use an instance of the SynchronousReader object only once (thus avoiding the two async calls racing with one failing to finish like you mentioned elsewhere) or you should implement IDisposable in order to unsubscribe from the event and prevent the memory leak.
A third solution might be possible: keep the single instance of SynchronousReader, but each call to SynchronousReader.Read would create a new instance of AsynchronousReader (rather than storing it as a private field within the instance). Then you could keep most of the code above which you don't like, but which properly handles event subscriptions.

Anonymous event handlers and disposing

I have a rather short question about anonymous event handlers:
This is the code that I have:
public void AddTestControl(Control ctrl)
{
ctrl.Disposed += (o, e) => { RemoveTestControl(ctrl); };
ctrl.SomeEvent += _Control_SomeEvent;
}
public void RemoveTestControl(Control ctrl)
{
ctrl.SomeEvent -= _Control_SomeEvent;
}
Is this code above fine, or should the code be rewritten in order to remove the Disposed Event Handler?
Something like this:
public void AddTestControl(Control ctrl)
{
ctrl.Disposed += _Control_Disposed;
ctrl.SomeEvent += _Control_SomeEvent;
}
public void RemoveTestControl(Control ctrl)
{
ctrl.Disposed -= _Control_Disposed;
ctrl.SomeEvent -= _Control_SomeEvent;
}
Generally, the only situation where you need to remove the event handlers from an object in order for it to be eligible for garbage collection is when the publisher object (the one defining the event) lives longer than the subscriber object (the one containing the event handlers). In such a situation the GC won't be able to release the subscriber when it goes out of scope since it's still being referenced by the publisher.
In this case, assuming this is WebForms or WinForms, the publisher (that is the Control object), is most likely a child object of the subscriber (probably a Page or a Form), which will be the first to go out of scope taking all its associated objects with it. Hence there's no need to remove the event handlers.
It always feels cleaner to me to unsubscribe from events, even in situations where I know the subscribers always outlive the publisher (the object raising the event): the event will never be raised again, the publisher is no longer reachable and can be collected.
Then again, how many people go to the trouble of unsubscribing every event handler in e.g. a WinForms application? The object references point from the publisher to the subscribers, not the other way around, so the publisher can be collected while the subscribers live on. It doesn't present the same danger as the opposite situation, where a long-lived publisher (e.g. a static event) can wastefully keep potentially large subscribers alive long after they could have been collected.
If you want/need to unsubscribe, then the requirement to unsubscribe the same delegate makes anonymous event handlers a bit of a pain. The Reactive Extensions solve this problem in a neat way: rather than having to remember the delegate you subscribed, subscribing returns an IDisposable which unsubscribes when disposed. Chucking all your subscriptions into a CompositeDisposable lets you unsubscribe everything with just one Dispose call.
Both codez are fine, but I like second as a matter of personal preference. It reads clearer than the first.
On top of it with the first code, there's anonymous lambda delegate and it gets a current reference to ctrl. That code may behave unexpectedly depending on situation and compile optimisation settings: whether or not the call is inlined or not.
Not to mention that there's architectural problem with the code: you have ControlOwner and a bunch of Child Controls. I take it you're adding child controls to ControlOwner at runtime, and then trying to react to their behavivour by subscribing ControlOwner to the childControl events. This is fine for events like _ButtonClicked etc. But not good for Dispose. Let the child control handle it's disposing on itself, the OwnerControl doesn't need to know about it. Not to mention that it may not exist at a time ChildControl[n].Dispose is called.
In short:
* it is better to leave dispose event on ChildControl alone and do all clean up in ChildControl.Dispose
* it is not necessary to unsubscribe from events. Event dispatcher will check if subscriber is alive.

Eventhandlers and application lifetime objects in c# - should I unhook?

Say I've got an object that exists for the duration of an application. Let's call it GlobalWorker. GlobalWorker has events e.g. UserLoggedIn to which other objects can subscribe. Now imagine I've got a Silverlight page or an asp.net page or something, that subscribes to the UserLoggedIn event when it is constructed.
public SomePage()
{
GlobalWorker.Instance.UserLoggedIn += new EventHandler(OnUserLoggedIn);
}
private void OnLoggedIn(object sender, EventArgs e)
{
}
Does the existence of this event prevent the page from being garbage collected? If so, what's the best pattern to use in this instance: weak event-handlers, move the subscription to the Load event and unsubscribe in the UnLoad event?
Use Weak Events.
This is a common problem in WPF and it is good you have thought about it.
Yes the behavior prevents the page from being GC.
The reason being is that UserLoggedIn will hold a reference to SomePage indefinitely. There is no explicit removal of the handler and since weak events are not being used it will not implicitly get removed either.
You can use weak events as another poster stated, you can also re-think your design to some degree and see if you can functionalize or encapsulate the eventing behavior. Perhaps the data is all that needs to be global in this instance (user credentials), where as the event can be kept isolated.
You could also de-register in the handler itself if this was a one-off event you cared about. It really boils down to your specific need and instance, weak event pattern is the pattern to deal with this application wide but does not mean you have to use that pattern in each and every instance this problem surfaces.

Is unwired event a memory leak?

If yes, is there a way to unwire it globally for all wired events
Edit: Say for example. I have objects, each tagged with an event like orm.NatureChanged += Nature_Changed; I tag these events when i create each orm instance. If I didn't unwire by means like orm.NatureChanged -= Nature_Changed; will it cause memory leak?
Regardless of what you're asking, the technical answer to your question is "no". Technically, unless you discover a bug in the CLR, there are no true "memory leaks" with managed objects (that's a big part of what makes them a Good Thing). To answer what I think you're actually asking, though, it sounds like you're asking one of two things:
Is there something that needs to be done with events that do not have any delegates attached to them?
Can an event prevent objects from getting cleaned up by the garbage collector?
The answer to the first question is simply "no". Move along, nothing to see here.
The answer to the second has been discussed at length here on SO and other areas of the web. The short version is that an attached event handler means that the GC will consider the target instance as "reachable" by the event-firing instance. This can cause objects to remain in memory longer than expected, since this reachability is somewhat transparent to the user (developer) because of the way delegates are constructed.
In other words, say I have two objects: Producer and Consumer. Producer fires an event that Consumer...consumes.
public class Producer
{
public event EventHandler OmgIDidSomething;
}
public class Consumer
{
public void AttachTo(Producer producer)
{
producer.OmgIDidSomething += new EventHandler(producer_OmgIDidSomething);
}
private void producer_OmgIDidSomething(object sender, EventArgs e)
{
// ...
}
}
In this example, any instance of Consumer where AttachTo is called will remain reachable as far as the GC is concerned until the instance of Producer that it attached to is eligible for collection, because the delegate behind the implementation of the OmgIDidSomething event has a reference to the instance of Consumer that it corresponds to.
No, because when you unwire an event, the delegate (it's an object) which was wired to the event is no longer rooted, and will be collected when the GC sees fit to do so. This is assuming of course the event delegate isn't attached to multiple handlers, in which case it won't be collected until it is unwired from all events.
If you meant whether events that don't get unwired can cause a memory leak, the answer is that it can if the actual lifetime of the object holding the event delegate is much longer than the useful lifetime of the object to which the delegate refers. For example, if a collection's enumerator hooked a CollectionChanged event, and someone were to get enumerators without ever disposing them, then every time the collection was enumerated (without disposing the enumerator) a new enumerator object would be created that would stay in memory as long as the underlying collection.
It's not a memory leak, it just doesn't hook any handlers to that event if they aren't wired, automatically or otherwise. So the event fires to nobody, gets cleaned up, and life goes on.
This conversation talks on this subject: How do events cause memory leaks in C# and how do Weak References help mitigate that?
See some background information here: What does AutoEventWireUp page property mean?

Categories