简体   繁体   English

弱事件和GC

[英]Weak events and GC

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")? 还是应该强迫GC避免这种情况(确定性的“清理”)? Something else? 还有吗

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. 如果在ev = MyEventev.Invoke之间未注册委托,则它仍将尽早收到通知。 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. 这不像是部分收集了对象或其他任何东西-只是尚未收集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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