【问题标题】:Which is the better approach to invoke an event delegate?调用事件委托的更好方法是什么?
【发布时间】:2013-02-22 08:21:57
【问题描述】:
private void NotifyFreeChannelsChanged() //1.
{
    if (FreeChannelsChanged != null)
    {
        FreeChannelsChanged(this, null);
    }
}

private void NotifyFreeChannelsChanged() //2.
{
    NotifyCollectionChangedEventHandler h = FreeChannelsChanged ;
     if (h != null)
         h(this, e);
}

其中哪些更好,为什么。或者这只是一个额外的检查。差别不大。

【问题讨论】:

标签: c# events event-handling


【解决方案1】:

“更好”?好吧,不包含(特定的)竞争条件,一个。 MultiCastDelegate 类型是不可变的,并以所有重要的方式使用值类型语义(它们引用类型,但是,请参阅this,更重要的是,this),这就是您首先分配它的原因然后检查。问题是:

// this evaluates to true...
if(SomeEvent != null)
{
    // ...but before this line executes, the last 
    // subscriber detached, and now SomeEvent is null. Oops.
    SomeEvent(this, e);
}

您应该问“为什么有人会使用示例 #2?”


顺便说一句,这是使用隐式类型变量 (var) 的好地方。那些委托类型名称变长了...

同样有趣的是竞争条件仍然存在,只是更加微妙。如果在分配后删除订阅者会发生什么?好吧,它仍然会被调用,但你真的无能为力(我知道)。

【讨论】:

    【解决方案2】:

    第二个很容易适用于我们使用的一组扩展方法,其中 EventHandler 是方法的目标。

    public static void Raise(this EventHandler handler, object sender)
    {
      if (handler != null)
        handler(sender, EventArgs.Empty);
    }
    
    // And then...
    TheEvent.Raise(this);
    

    据我所知,将处理程序传递给方法的事实为您提供了本地副本以避免竞争条件。

    【讨论】:

      【解决方案3】:

      第二个是防止可能的线程错误,其中在 null 检查和 sn-p 1 中触发的事件之间发生上下文切换。其他一些线程可以在两者之间将其设置为 null。

      因此,除非您的方法倾向于多线程,否则您可以使用更简单的 sn-p 方法。

      【讨论】:

      • 我只是选择一起避免竞争条件,无论我希望在编写代码时如何调用代码。它不需要任何费用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多