简体   繁体   English

在C#中调用事件处理程序

[英]Calling an event handler in C#

I've been trying to learn how to use event handlers in C# but I can't figure out what handler(this, e) does in the following code: 我一直在努力学习如何在C#中使用事件处理程序,但我无法弄清楚以下代码中的处理程序(this,e):

public event EventHandler ThresholdReached;

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

Is it trying to call the event handler method (this) with the event (e)? 它是否尝试使用事件(e)调用事件处理程序方法(this)?

It invokes all registered event listeners which are registered on the ThresholdReached event. 它调用在ThresholdReached事件上注册的所有已注册事件侦听器。

The handler != null check makes sure at least one listener is registered to that event. handler != null check确保至少有一个侦听器注册到该事件。

In C# 6.0 and above you can use Null Propagation : 在C#6.0及更高版本中,您可以使用Null Propagation

handler?.Invoke(this, e);

handler(this, e) will call every registered event listener. handler(this, e)将调用每个注册的事件监听器。 Event listeners subscribe with help of the += operator and unsubscribe with -= operator to that event. 事件侦听器在+=运算符的帮助下订阅,并使用-=运算符取消订阅该事件。

this is there to give the event listener to know who raised the ThresholdReached event. this是为了让事件监听器知道谁提出了ThresholdReached事件。 Who was the sender of the event. 谁是活动的发送者。

e is the event argument which is also passed into the listener method which can contain more useful informations about the ThresholdReached event eg which threshold was reached. e是事件参数,它也传递给侦听器方法,该方法可以包含有关ThresholdReached事件的更多有用信息,例如达到了哪个阈值。

It is raising a ThresholdReached event with arguments sender=this and eventarguments = e. 它使用参数sender = this和eventarguments = e引发ThresholdReached事件。 In fact, it is the same as the following; 实际上,它与以下相同;

public event EventHandler ThresholdReached;

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

If there are any listeners to this event; 如果有任何听众参加此活动; it will simply call listener delegates; 它只会调用监听器代理;

this.ThresholdReached += new EventHandler(Form1_ThresholdReached);

Then, when this event is raised Form1_ThresholdReached function will be called with this and e parameters. 然后,当引发此事件时,将使用thise参数调用Form1_ThresholdReached函数。

The code in your example copies all registered handlers to the local variable handler , checks that the invocation list is not empty and invokes all members of the copied invocation list with the arguments this and e . 示例中的代码将所有已注册的处理程序复制到本地变量handler ,检查调用列表是否为空,并使用参数thise调用复制的调用列表的所有成员。

The reason for the fact that you get a snapshot of the current invocation list is that delegates are immutable . 您获得当前调用列表的快照的原因是委托是不可变的 You get a reference to the current multicast delegate, and when handlers are added or removed the backing field points to a new delegate created from two immutable ones. 您将获得对当前多播委托的引用,并且在添加或删除处理程序时,支持字段指向从两个不可变的委托创建的新委托。

The usual reason to copy the invocation list to a local variable is some form of thread-safety: a handler could be unsubscribed between the usual nullity check (check that the invocation list isn't empty) and the actual invocation: that way you might accidentally fire an event with no handlers and a NullReferenceException would be thrown. 将调用列表复制到局部变量的通常原因是某种形式的线程安全:处理程序可以在通常的无效性检查(检查调用列表不为空)和实际调用之间取消订阅:这样你可能会意外触发没有处理程序的事件,并抛出NullReferenceException

Is it trying to call the event handler method (this) with the event (e)? 它是否尝试使用事件(e)调用事件处理程序方法(this)?

No, not literally. 不,不是字面上的。 It is calling the event handler with the EventArgs e and using this as sender. 它调用与事件处理程序EventArgs e和使用this发件人。 It might as well be: 它可能是:

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

Or, to circumvent the null check: 或者,绕过空检查:

public event EventHandler ThresholdReached = delegate { };

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

But, as @Oded noted, the first piece isn't thread-safe, because EventHandler handler = ThresholdReached creates a copy of the handler, which is better explained in this question . 但是,正如@Oded所指出的那样,第一部分不是线程安全的,因为EventHandler handler = ThresholdReached创建了一个处理程序的副本,在这个问题中可以更好地解释。

handler refers to your ThresholdReached event. handler指的是您的ThresholdReached事件。 So, if anyone is subscribing to ThresholdReached events, their registered handler will be called with arguments this and e . 因此,如果有人订阅了ThresholdReached事件,则将使用参数thise调用其注册的处理程序。

It is Triggering the ThresholdReached event. 它是触发ThresholdReached事件。 Passing a reference to itself, this . 通过对自身的引用, this Passing arguments about the event in e . e传递关于事件的论点。

The call to handler represents a function call in another object or class. 对handler的调用表示另一个对象或类中的函数调用。 When you create the object, you will be able to write a piece of code that looks like this: 创建对象时,您将能够编写一段如下所示的代码:

obj.ThreasholdReached += new EventHandler(someFunction);

someFunction in that class will be defined like this someFunction中的someFunction将被定义为这样

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

the OnThreasholdReached function in the original object is what publishes the event to any other class that has assigned a function to the ThreasholdReached handler. 原始对象中的OnThreasholdReached函数将事件发布到已为ThreasholdReached处理程序分配函数的任何其他类。 Using handler as a go-between is an entirely unnecessary extra step. 使用handler作为中间人是一个完全不必要的额外步骤。 You are still saying if ThreasholdReached != null , its the same thing. 你还在说if ThreasholdReached != null ,它是一样的。

In Summary: The line of code handler(this, e) is actually the call to whatever subscriber someFunction(object sender, EventArgs e) has been assigned to the ThreasholdReached event of the object. 总结:代码handler(this, e)实际上是对任何订户someFunction(object sender, EventArgs e)已分配给对象的ThreasholdReached事件的调用。

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

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