究竟什么时候在C#中执行事件?

时间:2011-05-18 12:57:06

标签: c# event-handling

我开发了一个大量使用事件的C#应用​​程序。现在这个应用程序偶尔会做一些我无法理解的有趣的事情或追踪到它们应该发生的具体原因。我认为这些间歇性故障的原因是某些并发或竞争条件,我没想到。

C#中的事件究竟是如何处理的?如果引发了一个事件,那么(a)附加到该事件的代码部分是否会立即执行 ?或者,事件(b)是否会被放在一堆事件上,并且只要.NET认为它适合执行而其他代码在此期间被执行,就会被执行?

6 个答案:

答案 0 :(得分:12)

  

如果引发了某个事件,那么附加到该事件的代码部分会立即执行吗?

嗯,是的,不是。事件是多播委托,因此可能有零个,一个或多个“代码部分”附加到事件。在有很多的情况下,显然其中一个必须先行,其中一个必须先行。在事件发生时,第二个不会立即执行;它会在第一个事件处理程序正常完成后立即执行。

  

将事件放在一堆事件上,并在.NET认为适合执行时执行,同时执行其他代码吗?

假设您的应用程序写得不好并挂起了UI。当用户界面挂起时,用户点击按钮1和按钮2.由于应用程序挂起,所以没有任何可见的事情发生。单击按钮1和按钮2的事件不会触发。但是Windows已经创建了一个消息队列,并在其上排列了按钮1和按钮2具有在应用程序自行解除时需要处理的待处理点击的事实。当泵送消息循环时,按钮1单击事件将触发。当它完成它的事情时,消息循环再次被泵送并且按钮2单击事件触发。

所以是的,从那个意义上来说,事件排队并稍后执行,但它不是“当.NET认为它合适时”;当处理消息队列的线程再次开始处理消息队列时。这里没有神秘的Windows策略来控制你的代码。

答案 1 :(得分:8)

这完全取决于事件提升(和订阅)代码。

如果你正在举办这样的活动:

EventHandler handler = MyEvent;

if (handler != null)
{
    handler(this, EventArgs.Empty);
}

或类似的东西,然后立即执行所有事件处理程序。那是典型的实现......你必须更加努力地将每个事件委托放入WinForms消息队列或类似的东西。

如果您可以向我们提供有关您正在谈论的活动及其实施方式的更多信息,我们可能会为您提供更多帮助。

有关活动和代表的更多信息(以及它们之间的区别),您可以阅读my article on the topic

答案 2 :(得分:5)

C#事件,就像其他代表一样,在触发时立即执行

答案 3 :(得分:2)

除非另有明确说明,否则会同步调用事件。

通常,触发事件的代码如下所示:

public event EventHandler MyEvent;

protected virtual void OnMyEvent()
{
    EventHandler handler = MyEvent; // keep a copy to avoid race conditions
    if (handler != null)
        handler(this, EventArgs.Empty);
}

从这段代码中可以看出,事件处理程序是从OnMyEvent方法立即和同步调用的。

答案 4 :(得分:1)

我相信你的问题已在这里得到解答:

Are Event Handlers processed Asynchronously?

简而言之,它取决于您的实现,但默认事件处理是同步处理的。但是,有一些方法可以使它异步。

答案 5 :(得分:0)

如前面的awnser中所述,它完全取决于引发事件或处理事件的代码。

以上示例缺少的是如何引发/处理事件的正确代码。我知道它们只是简单的例子,但是,良好的做法很重要。

如果您想了解如何在C#中正确处理事件的良好示例/材料,您可以查看以下文章:http://www.codeproject.com/KB/cs/event_fundamentals.aspx