c#OnEventReached方法中的逻辑

时间:2015-11-04 19:54:06

标签: c# asp.net .net visual-studio

有人可以在举办活动时向我解释以下声明的重要性。

   EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;

由于我们只是将Threshold事件分配给处理程序,为什么我们不能简单地调用ThresholdReached(this,e)

    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
    {
        EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
        if (handler != null)
        {
            handler(this, e);
        }
    }
    public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;

1 个答案:

答案 0 :(得分:4)

拥有此第一行可防止多线程应用程序中的竞争条件。

想象一下,如果某个其他线程在您检查它是否为空之后取消订阅了事件。

检查null是必要的,因为没有任何处理程序的事件为null,并且您将通过调用此类事件获得NullReferenceException。

所以准确一点。

此代码不检查null并且可能抛出NullReferenceException:

protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
    ThresholdReached(this, e);
}

由于可能的竞争条件,这很危险,可能也会引发异常:

protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
    if (ThresholdReached != null)
         ThresholdReached(this, e);
}

编辑(为了更好地解释局部变量的行为):

具有此分配会创建保持其状态的事件的本地副本。因此,如果任何线程取消订阅事件本地副本,则在方法调用的其余部分中保持相同。换句话说,委托的行为类似于复制结构而不是复制引用。

下面的代码会打印文字:

        // let's assume ThresholdReached is null
        ThresholdReached += MyHandler;
        EventHandler<ThresholdReachedEventArgs> localCopy = ThresholdReached ;
        ThresholdReached -= Program_SthEvent;
        if (localCopy != null)
            Console.WriteLine("we have a copy!");

注意localCopy如何保持状态和值;