2

I have the following situation.

A List<WeakReference<MyClass>>, MyClass has an event called MyEvent. I iterate over the list, and for every alive reference, I might invoke the MyEvent on it's target.

In other parts of my code, I keep live references to these objects. Let's say the process looks something like this:

var list = new List<WeakReference<MyClass>>();
var a = new MyClass();
a.MyEvent += delegate {
    DoSomeStuff(a);
};
list.Add(new WeakReference<MyClass>(a));

Now let's say I have no further use of a, and decide to dispose of it. So now, a = null.

I have a periodic checks setup that clear the original list of dead references. What I'm wondering is, will this event handler I have hooked up keep the former a instance of MyClass alive, and in turn prevent me to clean it up from the list?

What if the event wasn't just a normal Action, but instead an Action<MyClass> that passed itself as the parameter to the handlers? In a way, that handler still has a reference to the original object, even though the handler might never get called.

This might be really obvious and I can think of similar situations where I'd know the answer but the fact that I'm hooking that function on the very object makes me suspicious. If it does keep it alive it breaks my whole system so I need to know.

Luka Horvat
  • 3,985
  • 2
  • 24
  • 45
  • The `list` you define does not contain `a` so you won't have to clear it from there. I assume you meant 'list.Add(new WeakReference(a));` ? – oerkelens Nov 13 '13 at 13:55
  • Having that item in that list will prevent it from being garbage-collected, AFAIK. That's how garbage collection works. What are you actually trying to achieve with your lists? What exactly do you mean by "alive" in this case? – Frosty840 Nov 13 '13 at 14:00
  • as mentioned http://stackoverflow.com/questions/9531211/anonymous-event-handlers-and-disposing here as well i think the _publisher_ has a reference to the _subscriber_, not the other way around. Since a is your publisher, once you dispose a, it should be collected. #Frosty840: if i understand WeakReference a little bit, it _does_ enable GC on the object. – oerkelens Nov 13 '13 at 14:08
  • @oerkelens Ah. I'd assumed that WeakReference was something the OP was trying to achieve, rather than a standard framework class. My bad. I'll go fill some gaps in my knowledge. Thanks for the info. – Frosty840 Nov 13 '13 at 14:13
  • 3
    An object is alive if there are any paths to it from roots. The only root in your sample above is the list, but weak references do not keep their targets alive, so that root Is a dead end. There are no further roots, so the object is dead. Another way to look at it to look at who might keep the object formerly known as `a` alive. The only reference to `a` is from the delegate. Is the delegate accessible from a root? The only reference to the delegate is from `a`. This is a classic circular reference which GC knows how to collect. – Raymond Chen Nov 13 '13 at 14:20
  • Awesome. Thanks for the help guys. – Luka Horvat Nov 13 '13 at 17:12
  • I have to say, I've never found use for the weak reference stuff. If I have something hanging around then it is usually a problem with my architecture. What I am wondering is given A.MyEvent += B.MyHandler, I know A keeps B alive. But does B keep A alive? I ask this hear because if I asked it in a separate question people would report it as a duplicate of this one anyway even though it is not. – Jordan Dec 15 '14 at 14:41
  • @Jordan Isn't that what my question is asking? – Luka Horvat Dec 15 '14 at 16:31
  • I read this all once before, and I didn't think so, but after rereading "publisher has a reference to the subscriber, not the other way around", I believe I have my answer. The publisher is A, and the subscriber would be B. That said B would not keep A alive. That means that the publish/subscribe must use some sort of weak association to list subscribers. Interesting. – Jordan Dec 15 '14 at 16:41
  • To my first issue. I find that it is much more robust to maintain the lifetime of objects rather than simply hold on to them weakly. If you can break all ties to an object deterministically (e.g., using an IDisposable pattern), you will save yourself a great deal of pain. I learned this the hard way. I avoid WeakReference unless I have no other choice. Like if I am using objects from another assembly, and I do not control their lifetimes and have no way to know when that lifetime has expired. – Jordan Dec 15 '14 at 16:45
  • @Jordan I used weak references because I had a system that did something and then an "observer" that did cleanup when the system decided not to use an object anymore. The same can't be achieved with IDisposable because you would always have to dispose manually. – Luka Horvat Dec 15 '14 at 16:48
  • @LukaHorvat, there are situations where you have no choice. Just my advice. – Jordan Dec 15 '14 at 16:50

0 Answers0