Too many times we fi开发者_开发百科nd out that strange behavior / performance issues in the system are caused by "dead" events - events that invoked on freed objects. It looks like you need to always release (-=) existing event before registering a new one. This looks like best practice but how can we detect such a situation in existing code? Is there a tool which can spot a problem in the code relating to freeing events?
Hope my question was clear,
Thanks
Adi Barda
You could use event accessors to keep track of when an event is registered or unregistered.
The simplest way to avoid this situation is to use the compiler. If you only want to allow one delegate at a time, don't declare it as an event (which is inherently multicast), but as a plain delegate.
In other words, rather than having:
public event MyDelegateType MyEvent;
Use the following:
public MyDelegateType MyEvent;
Then the callers, rather than composing the delegate with +=
, simply assign to it with =
, implicitly removing the previous delegate.
Have a look at this article, which discusses the situation you have, and provides some links to some tools that can profile your code.
http://msdn.microsoft.com/en-us/library/ee658248.aspx
As always, be explicit and forget that GC exists (irony). Do the -= and sleep well.
Alternative, a hack, WeakReferences..
It looks like you need to always release (-=) existing event before registering a new one.
There is a flaw in this. You do not need to release an existing event before registering a new handler - there are many times when you want to have more than one object subscribing to a single event source. This is a common, and very useful, practice.
The issue is more commonly not unsubscribing to an event when you are finished listening to it. The GC will clean this up when the source and listener both become unrooted, but until then, it can prevent certain objects from being released.
The general rule of thumb I follow is this:
If you can easily track when you want to subscribe and unsubscribe (ie: you have a fixed lifetime, and its shorter than the lifetime of the event source), you should subscribe and unsubscribe yourself appropriately.
If you cannot track when you should unsubscribe, for example, if the lifetime of your class or the source object is indeterminate for some reason, or the source may need to be disposed prior to when you will be disposed, use the WeakEvent pattern.
精彩评论