Given an 'event', how do I obtain underlying delegates ?

  • Thread starter The One We Call 'Dave'
  • Start date
T

The One We Call 'Dave'

Hi,

Various custom controls in my WinForms application register for the
'Application.Idle' event on load, and unregister on dispose. To avoid memory
leaks, it's essential that I remember to unregister on dispose.

Before my application exits, I'd like to do an 'assert' to assure myself
that there are no cases in which I've forgotten to unregister. I was under
the impression that an event is nothing more than a collection of delegates.
I therefore tried:

Debug.Assert(Application.Idle.Count==0);

This doesn't compile, however, and begs the question: Given an event
object, how do I obtain the underlying delegate collection?

Dave
 
K

Kevin Spencer

What makes you think you need to do that?

You don't.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
You can lead a fish to a bicycle,
but it takes a very long time,
and the bicycle has to *want* to change.
 
A

Alan Pretre

The One We Call 'Dave' said:
Given an event object, how do I obtain the underlying delegate collection?

I think something along these lines:

// Number of subscribers to the event:
int n = Idle.GetInvocationList().Length;

- OR -

// Get at each subscriber:
System.Delegate[] DelegateList = Idle.GetInvocationList();
foreach (IdleDelegate Delegate in DelegateList) {
...
}


-- Alan
 
C

chris martin

The One We Call 'Dave' said:
Given an event object, how do I obtain the underlying delegate
collection?
I think something along these lines:

// Number of subscribers to the event:
int n = Idle.GetInvocationList().Length;
- OR -

// Get at each subscriber:
System.Delegate[] DelegateList = Idle.GetInvocationList();
foreach (IdleDelegate Delegate in DelegateList) {
...
}

Both of those will result in compiler error "The event...can only appear
on the left hand side of += or -=";

This is a fun one and I'm experimenting with it right now.

Chri
 
J

Jon Shemitz

Various custom controls in my WinForms application register for the
'Application.Idle' event on load, and unregister on dispose. To avoid memory
leaks, it's essential that I remember to unregister on dispose.

If the control is disposed of while the app still runs, yes.
Before my application exits, I'd like to do an 'assert' to assure myself
that there are no cases in which I've forgotten to unregister. I was under
the impression that an event is nothing more than a collection of delegates.
I therefore tried:

When your app exits, the Application.Idle event goes with it.
Application.Idle is 'just' WinForms' way of multiplexing the idle
proc. There should be no consequences of terminating an app with a
populated Application.Idle.
Debug.Assert(Application.Idle.Count==0);

This doesn't compile, however, and begs the question: Given an event
object, how do I obtain the underlying delegate collection?

So far as I know (and I just yesterday found how far from
comprehensive my understanding of events is) you don't: the only
things you can do with another class's event is += and -= it.
 
T

The One We Call 'Dave'

What makes you think you need to do that?
You don't.

You most certainly do. 'Application.Idle' is a static event. If you fail
to unregister, the reference will be held in the event collection until the
Application terminates. This constitutes a memory leak. Just to confirm, I
looked up the event in MSDN and found this excerpt:

Because this is a static event, you must detach any event handlers
attached to this event in the ApplicationExit event. If you do not detach
these handlers, they will remain attached to the event and continue to
consume memory.
David
 
T

The One We Call 'Dave'

I think something along these lines:
// Number of subscribers to the event:
int n = Idle.GetInvocationList().Length;

Thanks for the reply.

I had a similar thought, but I get the following compilation error:

Error 1 The event 'System.Windows.Forms.Application.Idle' can only appear on
the left hand side of += or -=

David
 
C

chris martin

What makes you think you need to do that?
You most certainly do. 'Application.Idle' is a static event. If
you fail to unregister, the reference will be held in the event
collection until the Application terminates. This constitutes a memory
leak. Just to confirm, I looked up the event in MSDN and found this
excerpt:

Because this is a static event, you must detach any event handlers
attached to this event in the ApplicationExit event. If you do not
detach
these handlers, they will remain attached to the event and continue to
consume memory.
David

Take a look at this Dave.

I just tested it and it's golden!

http://tinyurl.com/ao25
 
T

The One We Call 'Dave'

When your app exits, the Application.Idle event goes with it.
Application.Idle is 'just' WinForms' way of multiplexing the idle
proc. There should be no consequences of terminating an app with a
populated Application.Idle.

Ah, now I see why Kevin made the comment that he did. I didn't express
myself clearly (sorry kevin).

I didn't mean to imply that there were negative consequences of terminating
the app with a bunch of Application.Idle callbacks in place. The only reason
I want to perform the assert is to confirm with myself that I'm not
forgetting to unregster these handlers.

My WinForms app will be active for weeks at a time. Many controls will be
created and subsequently disposed during that period. If I forget to
unregister these handlers, the effect of the memory leak will build up over
the lifetime of the application session. I thought that running an assert
just prior to exit would be a clever way to determine during the development
phase whether I was failing to clean up any of these handlers.

David
 
C

chris martin

Take a look at this Dave.
Oh my! Well, I certainly wouldn't have guessed approach that on my
own. :) Thanks, I'll try it.

After screwing with this, trying to find an answer (before the googlin'),
this was definately where I was heading. My stuff was way uglier though.

That class I linked is a keeper methinks
 
N

Nicholas Paldino [.NET/C# MVP]

Dave,

I am curious why you want to do this before your application exits.
From a cleanup point of view, the app domain is going to be torn down,
meaning your objects are going to be collected. On top of that, your
process is going to disappear. Given that event handlers (methods on
objects) are not resources that need to be reclaimed at the risk of
something detrimental, it doesn't seem to be a big deal to me, at the time
your app shuts down.

The other concerns you have are valid, about your class/control
unsubscribing to the Idle event. However, your assertion is wrong, because
you assume that your classes are the only ones subscribing. What if there
are elements of the framework that subscribe, and are ok with doing so for
the lifetime of the app? What do you do then?

The best you can do is make sure your classes implement IDisposable, to
indicate that lifetime management needs to be a consideration when using the
class, and make sure to unsubscribe when done.

Hope this helps.
 
K

Kevin Spencer

Ah, now I see why Kevin made the comment that he did. I didn't express
myself clearly (sorry kevin).

No need to apologize. I am well aware of my communication difficulties. I'm
sure it was as much my fault as yours!

In any case, I see you've straightened it out. All's well that ends well!

--

Kevin Spencer
Microsoft MVP
..Net Developer
You can lead a fish to a bicycle,
but it takes a very long time,
and the bicycle has to *want* to change.
 

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