C# 中的事件到底什么时候执行?
我开发了一个大量使用事件的 C# 应用程序。现在这个应用程序偶尔会做一些有趣的事情,我无法理解或追踪到它们发生的具体原因。我认为这些间歇性故障的原因是某种我没有预料到的并发或竞争条件。
C# 中到底是如何处理事件的?如果引发事件,(a) 附加到该事件的代码部分是否会立即执行?或者,事件 (b) 是否会被放入事件堆栈中,并在 .NET 认为适合执行时执行,同时执行其他代码?
I have developed a C# application which makes heavy use of events. Now this application is occasionally doing funny things that I cannot understand or track down to a specific cause why they should occur. I reckon that the cause for these intermittent malfunctions is some sort of concurrency or race condition which I did not anticipate.
How exactly are events handled in C#? If an event is raised, will (a) the portion of code attached to that event be executed immediately? Or will the event (b) be put on a stack of events and be executed whenever .NET deems it suitable for execution while other code is executed in the meantime?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
嗯,是的,也不是。事件是多播委托,因此可能有零个、一个或多个附加到事件的“代码部分”。在有很多人的情况下,显然其中一个必须先走,而其中一个必须后走。第二个事件不会在事件发生后立即执行;它在第一个事件处理程序正常完成后立即执行。
假设您的应用程序编写得不好并且导致 UI 挂起。当 UI 挂起时,用户单击按钮 1 和按钮 2。由于应用程序挂起,因此不会发生任何可见的情况。单击按钮 1 和按钮 2 的事件不会触发。但是 Windows 创建了一个消息队列,并将按钮 1 和按钮 2 具有待处理的单击的事实排入队列,这些单击需要在应用程序自行取消挂起时进行处理。当消息循环被泵送时,按钮 1 单击事件将被触发。当它完成它的工作时,消息循环再次被泵送并且按钮 2 单击事件被触发。
所以是的,从这个意义上说,事件会排队并稍后执行,但这不是“当 .NET 认为合适时”;而是“当 .NET 认为合适时”。当正在处理消息队列的线程再次开始处理消息队列时。这里没有神秘的 Windows 策略来控制您的代码。
Well, yes and no. Events are multicast delegates, so there might be zero, one or many "portions of code" attached to an event. In the scenario where there are many, clearly one of them has to go first and one of them has to go second. The one that goes second isn't executed immediately upon the event being raised; it's executed immediately upon the first event handler completing normally.
Suppose your application is badly written and hangs the UI. While the UI is hung, the user clicks on button 1 and button 2. Since the application is hung, nothing visible happens. The events for button 1 and button 2 being clicked do not fire. But Windows has created a message queue and enqueued on it the fact that button 1 and button 2 have pending clicks that need to be processed when the application unhangs itself. When the message loop is pumped then the button 1 click event fires. When it is done doing its thing, the message loop is pumped again and the button 2 click event fires.
So yes, in that sense events are queued up and executed later, but it is not "when .NET deems it suitable"; it's when the thread that is processing the message queue starts processing the message queue again. There's no mysterious Windows policy in here controlling your code.
它完全取决于事件引发(和订阅)代码。
如果您像这样引发事件:
或类似的事情,那么所有事件处理程序将立即执行。这是典型的实现...您必须更加努力地将每个事件委托放入 WinForms 消息队列或类似的东西中。
如果您可以向我们提供有关您所讨论的事件及其实施方式的更多信息,我们也许能够为您提供更多帮助。
有关事件和委托(以及它们之间的区别)的更多信息,您可能希望阅读我的文章主题。
It entirely depends on the event raising (and subscription) code.
If you're raising the event like this:
or something similar, then all the event handlers will be executed immediately. That's the typical implementation... you have to work a bit harder to put each event delegate into WinForms message queue or something like that.
If you could give us more information about what events you're talking about and how they're implemented, we may be able to help you more.
For more information on events and delegates (and the difference between them) you may wish to read my article on the topic.
C# 事件与其他委托一样,在触发时立即执行。
C# events, just like the rest of delegates, are executed immediately when triggered.
除非明确实现,否则事件将被同步调用。
通常,触发事件的代码如下所示:
正如您从这段代码中看到的,事件处理程序是从
OnMyEvent
方法立即同步调用的。Unless explicitly implemented otherwise, events are called synchronously.
Typically the code that triggers an event looks like that:
As you can see from this code, event handlers are called immediately and synchronously from the
OnMyEvent
method.我相信您的问题已在这里得到解答:
事件处理程序是否异步处理?
简而言之,这取决于您的实现,但默认事件处理是同步处理的。然而,有一些方法可以使其异步。
I believe your question has been answered here:
Are Event Handlers processed Asynchronously?
In short, it depends on your implementation, but the default event handling is processed synchronously. There are, however, ways to make it asynchronous.
如前文所述,它完全取决于引发事件或处理事件的代码。
上面的示例缺少的是有关如何引发/处理事件的正确代码。我知道它们只是简单的示例,但尽管如此,良好的实践很重要。
如果您想要有关如何在 C# 中正确处理事件的良好示例/材料,您可以查看这篇文章:http://www.codeproject.com/KB/cs/event_fundamentals.aspx
As stated in the previous awnser, it entirely depends on the code that is raising the event or handeling the event.
What above examples are missing is properly code on how to raise/handle events. I'm aware that they're just quick examples, but nonetheless, good practise is important.
If you want good examples/material on how events can be properly processed in C#, you could take a look at this article: http://www.codeproject.com/KB/cs/event_fundamentals.aspx