GC and events

A

Aleksey

Hi all!
It's a theoretical question.
Suppose I have object A with event OnAction and I have object B that
connects to this event.
I create object B as a local method variable and in this method I connect
object B to OnAction of object A.
So after the method has finished running, the only way to reach object B
is event in class A.
How GC works in this case? Is it remove object B? If not than it may be a
memory leak here!!!

Best regards
 
G

Guest

Hi Aleksey,
The GC will not remove B, the garbage collector will not consider an
object for collection until it is not longer referenced by any other
reference. In this case B will live on until A no longer has any references
and then it will stay around until the GC runs (if it has a finalizer it will
live even longer). What you want to do if unregister B from the event using
the -= syntax to remove B from the OnAction multicast delegates
InvocationList.

Mark.
 
D

David Browne

Aleksey said:
Hi all!
It's a theoretical question.
Suppose I have object A with event OnAction and I have object B that
connects to this event.
I create object B as a local method variable and in this method I connect
object B to OnAction of object A.


A has a reference to B's method, and B is reachable from A.

So after the method has finished running, the only way to reach object B
is event in class A.
Yes.

How GC works in this case? Is it remove object B? If not than it may be a
memory leak here!!!

Yes. This is a very common source of memory leaks in .NET. If A is
long-lived and B is not supposed to be, you must remove B from A's delegate
invocation list. Commonly this is done by making B follow the Disposable
pattern, and removing the event handlers in the Dispose method.

David
 
B

Bruce Wood

Aleksey said:
Hi all!
It's a theoretical question.
Suppose I have object A with event OnAction and I have object B that
connects to this event.
I create object B as a local method variable and in this method I connect
object B to OnAction of object A.
So after the method has finished running, the only way to reach object B
is event in class A.
Correct.

How GC works in this case? Is it remove object B? If not than it may be a
memory leak here!!!

Technically, it's not a memory leak because B is still accessible via
A. However, that "technically" is often cold comfort to those who find
themselves in this situation. From the programmer's conceptual level,
then, it may be a "memory leak": memory that's sticking around when the
programmer intended that it be GC'd.

Remember: event delegates are just pointers. If B subscribes to an
event of A, then A contains a pointer to B, and, as such, B is not
eligible for garbage collection until A is.

However, here's an even worse example.

You have class A that exposes a _static event_ OnActionStatic. B
subscribes to OnActionStatic and then the only other reference to B
goes out of scope. Now B will never be garbage collected until the
program terminates, because the static event chain lives for the life
of the program.

There are two ways to solve this problem.

1. Before B goes out of scope, unsubscribe from the offending event so
that there are no more references to B and it is therefore eligible for
GC.

2. B subscribers to A's event via a "weak reference delegate". You can
search this group's archives for "weak reference delegate" for details.
Basically this says, "This reference (the event subscription) doesn't
count as a live reference when determining whether to garbage collect
this object."

I use number 2, myself. I have lots of static events in my system and
objects always subscribe to them via weak reference delegates.
 
B

Bruce Wood

Aleksey said:
Hi all!
It's a theoretical question.
Suppose I have object A with event OnAction and I have object B that
connects to this event.
I create object B as a local method variable and in this method I connect
object B to OnAction of object A.
So after the method has finished running, the only way to reach object B
is event in class A.
How GC works in this case? Is it remove object B? If not than it may be a
memory leak here!!!

While writing my original response I was trying to think of whether it
was possible to get into even more trouble: whether it was possible to
have a value type subscribe to an event, and leave the reference
pointing into the stack where the value type _was_ after the method
returned.

That's when I realized that having a value type subscribe to an event
would result in the value type being boxed onto the heap, and the
_boxed copy_ being subscribed as the event recipient. Since there would
be no other reference to the boxed copy of the value, The box would be
GC'd only when the object that raises the event was itself GC'd.

Ewww! Nasty! Yet another thing you don't want to do with value types....
 
C

Christof Nordiek

Aleksey said:
Hi all!
It's a theoretical question.
Suppose I have object A with event OnAction and I have object B that
connects to this event.
I create object B as a local method variable and in this method I connect
object B to OnAction of object A.

To be accurate, the object is not created as a local variable. Only a
reference to the object is stored there.
So after the method has finished running, the only way to reach object B
is event in class A.
How GC works in this case? Is it remove object B? If not than it may be a
memory leak here!!!

This would be even more, than a memory leak. The object would still be
listening to the event and handle it, using the CPU, and maybe other
resources, though obviously it will have no use anymore.

The problem generally arises, if the sender of the event lives longer than
the reciever/subscriber.
 

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