事件订阅者是否按订阅顺序调用?
假设事件订阅者按订阅顺序调用是否安全?
示例:
void One(object sender, EventArgs e) {}
void Two(object sender, EventArgs e) {}
event EventHandler foo;
foo += One;
foo += Two;
事件触发时,One() 是否总是在 Two() 之前调用?
编辑:
你当然不应该依赖它,我只是在想。 这个想法是,多播委托类似于命令模式。 所以我只是想知道。 通常,您会使用一个集合来保留命令的顺序,以便您可以执行撤消/重做/任何操作。
Is it safe to assume that event subscribers are called in order of subscription?
Example:
void One(object sender, EventArgs e) {}
void Two(object sender, EventArgs e) {}
event EventHandler foo;
foo += One;
foo += Two;
Is One() always called before Two() when the event is fired?
Edit:
You should ofcourse not rely on it, I was just thinking. The idea was, that multicast delegates are similary to the COMMAND pattern. So I was just wondering. Ususally you would use a collection that keeps the order for COMMANDs so you can do undo/redo/whatever.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
鉴于该实现,是的,它们将始终按该顺序调用。
如果事件实际上使用某种奇怪而美妙的方式来处理订阅,它可能会做不同的事情 - 但“正常”实现会做正确的事情。
需要明确的是,订阅事件处理程序仅意味着调用事件的适当“添加”部分。 如果事件通过执行以下操作来处理此问题:
则会被转换为
Delegate.Combine< /a> 保证顺序。 但是,如果您有一个像这样的事件:
然后通过执行类似以下操作来触发该事件:
那么处理程序将以相反的顺序被调用。
摘要:对于所有理智的事件,您都可以依赖顺序。 理论上,事件可以做它们想做的事,但我从未见过一个事件不保持适当的顺序。
Given that implementation, yes, they will always be called in that order.
If the event actually uses some weird and wonderful way of handling subscriptions, it could do different things - but "normal" implementations will do the right thing.
To be clear, subscribing to an event handler just means invoking the appropriate "add" part of an event. If the event handles this by doing something like:
that gets translated into
and Delegate.Combine guarantees the ordering. However, if you had an event like this:
and then fired the event by doing something like:
then the handlers would be called in the reverse order.
Summary: For all sane events, you can rely on the ordering. In theory, events can do what they like, but I've never seen an event which doesn't maintain the appropriate ordering.
请密切注意乔恩·斯基特(Jon Skeet)给出的警告 - “鉴于该实施......”。 换句话说,进行最轻微的更改(多个线程、其他处理程序等),您就有可能失去执行顺序不变性。
不要不要依赖事件排序。 所有事件分派在逻辑上应该是独立的,就好像它们是并行发生的一样。 事件是逻辑上独立的动作。
我将更进一步,并断言,如果您必须假设事件触发的顺序,那么您存在严重的设计缺陷和/或滥用事件。
Pay very close attention to the caveats given by Jon Skeet - "Given that implementation...". In other words, make the slightest change (multiple threads, other handlers, etc.) and you risk losing the order-of-execution invariance.
Do NOT rely on event ordering. All event dispatches should be logically independent, as if they were occurring in parallel. Events are logically independent actions.
I'll go one step further, and assert that if you have to assume an order for events firing, you have a serious design flaw and/or are misusing events.
即使它们以正确的顺序调用,我也会尝试不编写依赖于先前已被解雇的委托才能正常运行的代码。
如果 Two() 依赖于 One() 正在执行的操作,则可以附加一个按正确顺序调用这两个方法的委托,或者在必要时让 Two() 调用 One()。
Even if they are called in the correct order I would try to not write code that relies on a previous delegate having been fired for it to function correctly.
If Two() is dependant on something that One() is doing then either attach a single delegate that calls the two methods in the correct order, or have Two() invoke One() when necessary.
快速回答是“这不关你的事”:)
事件本质上是异步的。 这意味着您不会等待事件被触发或期望它在给定时间发生。 它们就这样发生了,然后你就采取行动。 想要知道“何时”或试图弄清楚“如何”将会打破这种本性。
也许在这种情况下您不需要基于事件的方法来完成工作?
Jon Skeet 所说的对于当前实现来说在技术上是正确的,但在 c#8.5 或 VBasic 15.0 中可能不会。 依赖实施细节总是弊大于利。
The quick answer would be "It's none of your business" :)
An event is asynchronous by nature. This means that you are not waiting for an event to be fired or expecting it to occur at a given time. They just happen and then you take action. Wanting to know 'when' or trying to figure out 'how' is going to break this nature.
Maybe in this case you don't need an event-based approach to get things done?
What Jon Skeet said is technically correct for the current implementation, but maybe it won't in c#8.5 or VBasic 15.0. Relying on implementation details is always going to do more harm than good.
一般来说,事件订阅者的行为应该彼此独立。 无论它们是按订阅顺序、订阅的逆顺序调用,还是按每次引发事件时随机变化的看似随机的顺序调用,都应该没有什么区别。 订阅者不应该关心在他们之前或之后执行的其他订阅者。
然而,在某些情况下,事件可能会在此类排序很重要的上下文中使用。 事件处理程序可以传递一个可变对象,并期望利用该对象的先前处理程序的突变。 在这种情况下,如果事件的有意义的操作需要它们以特定的顺序执行,并且假设已经遵守了订阅者的任何记录的要求,则应该期望事件将按照给定的顺序执行。
In general, events subscribers are expected to behave independently from each other. It should make no difference whether they're invoked in order of subscription, reverse order of subscription, or in seemingly-random order which varies arbitrarily each time the event is raised. Subscribers shouldn't care about other subscribers that execute before them or after them.
In some cases, however, events may be used in contexts where such ordering is important. Event handlers may be passed a mutable object, and be expected to make use of previous handler's mutations of that object. In such a case, if meaningful operation of the events would require that they be performed in a particular order, and provided that any documented requirements for subscribers have been complied with, one should expect that the events will be executed in the order given.