2

In the following program...

using System;

class Program
{
    static Parent parent;

    static void Main( string[] args )
    {
        parent = new Parent();
        // The program hereafter runs for a long time and occasionally
        // causes parent.SomeEvent to be raised.
    }
}

class Parent
{
    public event EventHandler SomeEvent;

    public Parent()
    {
        new Handler( this );
    }
}

class Handler
{
    public Handler( Parent parent )
    {
        parent.SomeEvent += parent_SomeEvent;
    }

    void parent_SomeEvent( object sender, EventArgs e )
    {
        // Does something important here.
    }
}

Notice that the instantiated Handler object is not referenced, although it has subscribed to SomeEvent. Is it possible that, after the program is running for a while, the garbage collector may decide to eliminate the Handler instance and its parent_SomeEvent handler will therefore no longer be called whenever parent.SomeEvent is raised?

I need this clarification for an app I am writing. There are many Handler-like objects that are instantiated as shown above, without being referenced. The central purpose of Handler is to subscribe to SomeEvent. There are no useful methods to call on a reference to the Handler instance, so I would be fine not referencing it otherwise. I haven't encountered any problems while debugging. But now I am concerned that issues may arise after deployment when the app is running for long periods of time and the garbage collector is more active.

HappyNomad
  • 4,458
  • 4
  • 36
  • 55
  • Check out this post http://stackoverflow.com/questions/4526829/why-and-how-to-avoid-event-handler-memory-leaks for an in depth explaination – Osiris Mar 12 '13 at 19:41

3 Answers3

5

The instantiated object of your Handler class will not be garbage collected until all references to that object are removed.

Thus, until you unsubscribe all your event handlers, the object will live. Because the subscribed event handler is also another "reference" that connects the Parent instance to the Handler instance.

Is it possible that, after the program is running for a while, the garbage collector may decide to eliminate the Handler instance and its parent_SomeEvent handler will therefore no longer be called whenever parent.SomeEvent is raised?

That's exactly the reason why the GC only collects "unreferenced" objects from the heap. Your scenario would result in undefined NullReferenceExceptions, completely dependent on whenever the GC decides to delete objects. So luckily that's not the case :).

Furthermore, the GC is intelligent enough to determine isolated pools of unreferenced objects (unreferenced islands). So in the scenario your parent object also gets unreferenced, than the GC will determine the whole chain of objects are unreferenced (the Parent object, the event subscription, and the handler object) and will collect them all together on the next collect cycle.

If I may, I'd recommend this MSDN article. Gives you a nice overview of the broad concept of garbage collection in .NET. Very useful to keep in mind while coding.

bas
  • 13,550
  • 20
  • 69
  • 146
3

Program exists the whole time, and it's referring an instance of Parent, and thus Parent will never be garbage collected (until the program ends).

Parent keeps a collection of delegates through it's event handler SomeEvent, so any delegates in there won't be garbage collected.

So in short, no, it won't be garbage collected.

brain
  • 2,507
  • 1
  • 13
  • 12
2

When you run your program, the Parent class holds a reference to the EventHandler delegate instance you're creating in the Handler constructor, and the delegate instance holds a reference to the Handler instance. So the Handler instance will not be garbage collected as long as there is a reference to the Parent instance.

dtb
  • 213,145
  • 36
  • 401
  • 431