8

我一直在尝试学习如何在 C# 中使用事件处理程序,但我无法弄清楚 handler(this, e) 在以下代码中的作用:

public event EventHandler ThresholdReached;

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

是否尝试使用事件 (e) 调用事件处理程序方法 (this)?

4

7 回答 7

11

它调用在事件上注册的所有已注册事件侦听器ThresholdReached

handler != null检查确保至少有一个侦听器注册到该事件。

在 C# 6.0 及更高版本中,您可以使用Null Propagation

handler?.Invoke(this, e);

handler(this, e)将调用每个注册的事件监听器。事件侦听器在操作员的帮助下+=订阅,并通过操作员取消订阅-=该事件。

this是否可以让事件侦听器知道谁引发了 ThresholdReached 事件。谁是事件的发送者。

e是事件参数,它也被传递到侦听器方法中,它可以包含有关 ThresholdReached 事件的更多有用信息,例如达到哪个阈值。

于 2012-08-31T14:41:42.603 回答
1

ThresholdReached使用参数 sender=this 和 eventarguments = e 引发事件。其实跟下面是一样的;

public event EventHandler ThresholdReached;

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

如果该事件有任何监听者;它只会调用侦听器代表;

this.ThresholdReached += new EventHandler(Form1_ThresholdReached);

然后,当引发此事件时,Form1_ThresholdReached将使用thise参数调用函数。

于 2012-08-31T14:44:16.167 回答
1

您的示例中的代码将所有已注册的处理程序复制到局部变量handler,检查调用列表是否不为空,并使用参数this和调用复制的调用列表的所有成员e

您获得当前调用列表的快照的原因是委托是不可变的。您将获得对当前多播委托的引用,并且当添加或删除处理程序时,支持字段指向从两个不可变的委托创建的新委托。

将调用列表复制到局部变量的通常原因是某种形式的线程安全:处理程序可以在通常的空值检查(检查调用列表不为空)和实际调用之间取消订阅:这样你可能意外触发没有处理程序的事件,并且NullReferenceException会抛出 a。

于 2012-08-31T15:31:01.763 回答
0

是否尝试使用事件 (e) 调用事件处理程序方法 (this)?

不,不是字面意思。它使用EventArgse 调用事件处理程序并this用作发送者。也可能是:

if (ThresholdReached != null)
{
    ThresholdReached(this, e);
}

或者,为了规避空检查:

public event EventHandler ThresholdReached = delegate { };

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

但是,正如@Oded 所指出的,第一部分不是线程安全的,因为EventHandler handler = ThresholdReached创建了处理程序的副本,这在这个问题中得到了更好的解释。

于 2012-08-31T14:41:42.733 回答
0

handler指您的ThresholdReached活动。因此,如果有人订阅ThresholdReached事件,他们注册的处理程序将使用参数thise.

于 2012-08-31T14:43:08.893 回答
0

它正在触发ThresholdReached事件。传递对自身的引用,this. 在 中传递有关事件的参数e

于 2012-08-31T14:43:37.450 回答
0

对处理程序的调用表示另一个对象或类中的函数调用。创建对象时,您将能够编写如下所示的一段代码:

obj.ThreasholdReached += new EventHandler(someFunction);

someFunction在那个类中将像这样定义

public someFunction(object sender, EventArgs e) {...}

原始对象中的OnThreasholdReached函数是将事件发布到已将函数分配给 ThreasholdReached 处理程序的任何其他类。用作中间人handler是完全不必要的额外步骤。你还在说if ThreasholdReached != null,是一样的。

总结:这行代码handler(this, e)实际上是对someFunction(object sender, EventArgs e)已分配给对象的 ThreasholdReached 事件的任何订阅者的调用。

于 2012-08-31T14:52:13.527 回答