6

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?

Bobby
  • 11,419
  • 5
  • 44
  • 69
Prince Ashitaka
  • 8,623
  • 12
  • 48
  • 71
  • 2
    Do you mean an event which does not get unwired? – Bobby Sep 07 '10 at 18:24
  • Are you asking about event/delegates that have an empty invocation list? – Oded Sep 07 '10 at 18:26
  • @Bobby yes. 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? – Prince Ashitaka Sep 07 '10 at 18:36
  • A new SO question deals with this well: http://stackoverflow.com/questions/3662842/how-do-events-cause-memory-leaks-in-c-and-how-do-weak-references-help-mitigate-t – Scott Stafford Sep 08 '10 at 13:39

4 Answers4

8

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:

  1. Is there something that needs to be done with events that do not have any delegates attached to them?
  2. 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.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
5

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.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • Great! So, is there any way to globally unwind multiple handlers? – Prince Ashitaka Sep 07 '10 at 18:46
  • 1
    @Avatar: Unless you use reflection (and don't), it's impossible to access the invocation list of an event from outside the declaring class. So, no. – Adam Robinson Sep 07 '10 at 18:50
  • 2
    I suppose you could come up with some manual way of tracking which event was wired where, but this will become burdensome, and you really aren't going to get much from it. You'll probably waste more memory tracking the event to unwind it than to just let it be and let the gc dispose of it when it needs to. – kemiller2002 Sep 07 '10 at 18:54
  • @Adam Robinson Thanks a lot for speedy comment. – Prince Ashitaka Sep 07 '10 at 18:56
2

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?

Community
  • 1
  • 1
Scott Stafford
  • 43,764
  • 28
  • 129
  • 177
  • the 3662842 link was awesome. Really great indeed. I was thinking of asking about the lister=null explained in the answer session. It was really useful. – Prince Ashitaka Sep 08 '10 at 16:04
2

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.

supercat
  • 77,689
  • 9
  • 166
  • 211