弱事件和GC [英] Weak events and GC

查看:134
本文介绍了弱事件和GC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我无法确定性地取消订阅时,我正在使用弱事件(否则我会更喜欢 + = - = 而不是弱事件):

  class SomeType 
{
public SomeType(...)
{
//对象不知道它何时被移除
WeakEventManager(SomeSource,EventArgs).AddHandler(someSourceInstance,
nameof(SomeSource.SomeEvent),(s,e )=> {...});






$ b

这样如果对象是垃圾收集,那么事件处理程序将不会被调用。完美。

然而,如果object 尚未垃圾收集(但没有更强的引用),那么事件处理程序仍然会被调用。



我的问题是相当一般:在使用弱事件时我应该怎么做?在使用弱事件时,我应该在事件处理程序中期望无效的调用吗?或者我应该强制GC 避免这种情况(某种确定性的清理)?还有其他什么?

解决方案

您应该始终期待事件处理程序可能会在您注销后调用,即使使用强大事件。



最简单的场景在查看事件处理程序的执行方式时很明显:

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



$ b如果委托在 ev = MyEvent ev.Invoke ,它仍会尽早收到通知。我提到并发编程很难吗?

但在你的情况下,问题实际上是为什么对象不知道何时取消注册?回答这个问题,你会得到你的解决方案。为什么要调用一个事件处理程序来定位一个不再强烈引用的对象是非法操作?这不像是对象被部分收集或任何东西 - 它只是没有收集。


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?

解决方案

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.

这篇关于弱事件和GC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆