【问题标题】:When exactly are events executed in C#?C# 中的事件究竟是什么时候执行的?
【发布时间】:2011-05-18 12:57:06
【问题描述】:

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

在 C# 中究竟是如何处理事件的?如果引发了一个事件,(a)附加到该事件的代码部分是否会立即执行?还是将事件 (b) 放在事件堆栈中,并在 .NET 认为适合执行时执行,同时执行其他代码?

【问题讨论】:

    标签: c# event-handling


    【解决方案1】:

    如果引发事件,附加到该事件的代码部分是否会立即执行?

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

    是否将事件放在事件堆栈中,并在 .NET 认为适合执行时执行,同时执行其他代码?

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

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

    【讨论】:

    • "当它完成它的工作时,消息循环再次被抽出并且按钮 1 的点击事件被触发。"你是说按钮 2 的点击事件吗?”
    【解决方案2】:

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

    如果您要这样发起活动:

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

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

    如果您可以向我们提供有关您所谈论的事件及其实施方式的更多信息,我们或许可以为您提供更多帮助。

    有关事件和委托(以及它们之间的区别)的更多信息,您不妨阅读my article on the topic

    【讨论】:

      【解决方案3】:

      C# 事件,就像其他委托一样,在触发时立即执行。

      【讨论】:

        【解决方案4】:

        除非明确实现,否则事件会被同步调用。

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

        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 方法同步调用。

        【讨论】:

          【解决方案5】:

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

          Are Event Handlers processed Asynchronously?

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

          【讨论】:

            【解决方案6】:

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-05-17
              • 2012-06-01
              • 2011-08-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-04-15
              相关资源
              最近更新 更多