Weak events and GC

2019-07-09 00:53发布

问题:

I am using weak events when I can't deterministically unsubscribe (otherwise I would prefer += and -= instead of weak event):

class SomeType
{
    public SomeType(...)
    {
        // object doesn't know when it will be removed
        WeakEventManager(SomeSource, EventArgs).AddHandler(someSourceInstance,
            nameof(SomeSource.SomeEvent), (s, e) => { ... });
    }
 }

This way if object is garbage collected, then event handler will not be called. Perfect.

However. If object is not yet garbage collected (but there are no more strong references), then event handler will still be called.

My question is rather general: what should I do when using weak events? Should I expect invalid call in event handler when using weak events? Or should I force GC to avoid that case (kind of deterministic "clean up")? Something else?

回答1:

You should always expect an event handler may be called after you're unregistered, even with "strong" events. There's nothing invalid about such a call.

The simplest scenario is obvious when you look at how event handlers are executed:

protected void OnMyEvent(object sender, EventArgs e)
{
  var ev = MyEvent;
  if (ev != null) ev(this, EventArgs.Empty);
}

If a delegate is unregistered between ev = MyEvent and ev.Invoke, it will still receive the notification at the earliest opportunity. Have I mentioned that concurrent programming is hard yet?

But in your case, the problem really is "why doesn't the object know when to unregister?" Answer that, and you'll have your solution. Why would invoking an event handler that targets an object that is no longer strong referenced anywhere be an illegal operation? It's not like the object is partially collected or anything - it just wasn't collected yet.