Verifying object's events are not being observed before disposing

B

Bryan D.

Our application makes extensive use of C#'s event handling mechanism
to communicate between classes. A problem has cropped in that it
becomes difficult to know for sure that all observers of an object's
events have been deregistered when it's time to delete said object.
If some other object is registered for one of his events, he will not
get garbage collected and just lays around, receiving that event.

What I was hoping I could do would be to write a utility class that
could use Reflection on any object, walk over that object's events,
and then check to see if each event has a registered handler. This
does not appear to be doable through the means I've investigated
(Type.GetEvents(), EventInfo, EventDescriptor, etc.).

Does anyone have a good suggestion about how I could go about doing
this? Any strategies you've used to ensure event handlers are
deregistered when necessary?

Thank you all,
Bryan
 
A

Andreas Huber

Bryan said:
Our application makes extensive use of C#'s event handling mechanism
to communicate between classes. A problem has cropped in that it
becomes difficult to know for sure that all observers of an object's
events have been deregistered when it's time to delete said object.
If some other object is registered for one of his events, he will not
get garbage collected and just lays around, receiving that event.

I'm not entirely sure I understand what the problem is. Do you want one or
more of the subscribers to be GCed automatically when they are no longer
needed or is there a problem with publisher staying around (or both)?
What I was hoping I could do would be to write a utility class that
could use Reflection on any object, walk over that object's events,
and then check to see if each event has a registered handler. This
does not appear to be doable through the means I've investigated
(Type.GetEvents(), EventInfo, EventDescriptor, etc.).

AFAICT, reflection will only give you information about *classes* but not
objects. You want to know which object consumes events of which other
object.
Does anyone have a good suggestion about how I could go about doing
this? Any strategies you've used to ensure event handlers are
deregistered when necessary?

WeakReferences and dynamic invoke come to mind, but first we need to know
more accurately what your problem is. A short example program is always
best.

Regards,

Andreas
 
J

Jay B. Harlow [MVP - Outlook]

Bryan,
You do not need to use Reflection for this.

Remember that Events are implemented in terms of Delegates.

The System.Delegate class has a GetInvocationList method that returns a list
of all the handlers on the delegate.

You could check this invocation list to see if its empty, if not you could
empty it.

I don't have a sample, I would think setting the underlying delegate for the
event to null would clear the list.

Hope this helps
Jay
 
B

Bryan Dotzour

Thank you both for your replies. Let me try and restate my problem, I
think it was confusing because I wasn't sure how to go about the
problem.

Our application is a long-running app, possibly for days at a time, so
we want to make very sure that objects that are no longer being used are
actually getting properly disposed and garbage collected.

The issue that we've run into is that when an object is disposed it
needs to deregister all of it's event handlers, otherwise it won't get
garbage collected, even though the thing is out of scope and "disposed".

I believe that my first email had me mixed up and was thus confusing. I
guess what I really want to do is look at all of the Delegates on the
object I'm being disposed and see if their invocation list is empty, ala
Jay's suggestion. Reading that, it makes perfect sense, and that's what
I really want to do.

Thanks for the replies, and sorry for the confusing post.
Cheers!
 
A

Andreas Huber

Bryan said:
Thank you both for your replies. Let me try and restate my problem, I
think it was confusing because I wasn't sure how to go about the
problem.

Our application is a long-running app, possibly for days at a time, so
we want to make very sure that objects that are no longer being used
are actually getting properly disposed and garbage collected.

The issue that we've run into is that when an object is disposed it
needs to deregister all of it's event handlers, otherwise it won't get
garbage collected, even though the thing is out of scope and
"disposed".

IIUC, then the problem is that the subscriber lives longer than you want, as
in:

delegate void MyEventHandler();

sealed class Publisher
{
public event MyEventHandler SomethingHappened;

public void Publish()
{
this.SomethingHappened();
}
}

sealed class Subscriber : IDisposable
{
private readonly Publisher publisher;

public Subscriber( Publisher publisher )
{
this.publisher = publisher;
publisher.SomethingHappened +=
new MyEventHandler( publisher_SomethingHappened );
}

public void Dispose()
{
publisher.SomethingHappened -=
new MyEventHandler( publisher_SomethingHappened );
}

private void publisher_SomethingHappened()
{
// Whatever
}
}

sealed class MyMain
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber( publisher );
publisher.Publish();
// *** This does not make the subscriber go away ***
subscriber = null;

// more code
}
}


If this is the case, then one option is to make the subscriber disposable,
as I've done above. You would then simply call subscriber.Dispose() before
throwing it away and leave the rest to the garbage collector...

Regards,

Andreas
 
J

Jay B. Harlow [MVP - Outlook]

Andreas,
If this is the case, then one option is to make the subscriber disposable,
as I've done above. You would then simply call subscriber.Dispose() before
throwing it away and leave the rest to the garbage collector...
That is the way I would handle it, however having the Publisher check its
delegates Invocation List would allow a sanity check to make sure all the
subscribers are de-subscribing properly...

I'm not certain I would clean the invocation list, as much as log/throw some
sort of exception that says, hey wait I have subscribers who are still
subscribed... Or Hey wait these subscribers are still subscribed...

Just a thought
Jay
 
A

Andreas Huber

Jay said:
Andreas,
That is the way I would handle it, however having the Publisher check
its delegates Invocation List would allow a sanity check to make sure
all the subscribers are de-subscribing properly...

You mean you'd make Publisher disposable too and in Dispose() make sure that
all subscribers are deregistered? That certainly sounds like a good idea.

Regards,

Andreas
 
J

Jay B. Harlow [MVP - Outlook]

Andreas,
You mean you'd make Publisher disposable too and in Dispose() make sure that
all subscribers are deregistered? That certainly sounds like a good idea.
Yes.

Jay
 

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