简体   繁体   中英

How to create a Weak Referenced Event Handler?

I am doing research on how to properly create a weak referenced event handler. Since WPF has already a solution for avoiding memory leaks with events, I decompiled the "WeakEventManager" class and spent some time on analysing it.

As I found out, the "WeakEventManager" class relies on creating and storing a weak reference to the target object as well as to the event handler delegate. Here are some code segments:

this._list.Add(new WeakEventManager.Listener(target, handler));


  public Listener(object target, Delegate handler)
  {
       this._target = new WeakReference(target);
       this._handler = new WeakReference((object) handler);
  }

I am asking myself if this simple solution would already be working or did I overlook an important aspect, since most other solutions I found on the Internet are complex and hard to understand. The best solution I could find so far uses an unbound delegate. That is some kind of wrapper delegate that takes the event handler and event subscriber instance as a parameter (yes, it requires the event subscriber object to be passed in during delegate invocation).

You can find this great article here:

http://diditwith.net/CommentView,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx#commentstart

The "WeakEventManager" class doesnt't rely on knowing the subscriber class or any additional information. Beyond that it also works with anonymous delegates. Why do developers spent so much time on writing a solution that is not only working but also convenient to use, if a solution only requires them to store a weak reference to the delegate? What's the catch?

Update : Because someone downvoted this question (may be it is a little bit unspecific), I want to give a more precise question:

Is that source code above all it takes to create a working weak event handler? If not, what is missing?

did I overlook an important aspect

Yes, an important one. You traded one "leak" for another. Instead of preventing the event subscriber objects from getting garbage collected, you now prevent WeakReference objects from getting collected. You are not ahead.

What is also required is a mechanism to get those stale WeakReferences cleaned-up. You don't need them anymore when their IsAlive property returns false, you then remove it from _list . But you have to check that separately, some code needs to take care of that. An obvious choice is to check when an event is added or when it is fired. But that isn't enough, since client code only ever adds at initialization and you can't get a guarantee that the event is consistently fired.

So some kind of scheme is required to do it later. Anything is possible and nothing is quite ideal because it is a lot of busy-work with often not getting anything done. Making the right choice is important. And that certainly includes not doing this at all, it tends to be a band-aid over a design problem.

The idea behind the WeakEventManager is that it keeps a list of weak references to the target object of the events and a list of handlers it must call, but does not "tie them together" (as directly subscribing to events typically does), allowing the target to be garbage collected (and periodically checked so that the "subscribed" delegate list is emptied accordingly when the source is garbage collected).

This, which sounds easy, requires a lot of plumbing code, and that's all the WeakEventManager does (do the plumbing for you in an easy to use manner).

If you are cloning out WeakEventManager to your own implementation (or using the built-in) and it does that, then yes, that's all you need to do. If that's not what you are asking, then the question is unclear to me.

Is that source code above all it takes to create a working weak event handler? If not, what is missing?

That is the most important bit, the rest of the Listener class is important as well, not to mention the manual plumbing required to support this non-delegate event handler.

For instance check out ListenerList.DeliverEvent which is a bit more involved than the usual Invoke call.

Basically the normal event system assumes strong references so in order to use WeakReference you end up having to add a lot of the translation logic yourself as well as deciding how to handle events that never fire due to using WeakReference .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM