事件订阅者是否按订阅顺序调用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/374398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:03:46  来源:igfitidea点击:

Are event subscribers called in order of subscription?

c#.netevents.net-2.0c#-2.0

提问by EricSchaefer

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?

当事件被触发时,One() 是否总是在 Two() 之前调用?

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.

编辑:
你当然不应该依赖它,我只是在想。这个想法是,多播委托类似于命令模式。所以我只是想知道。通常,您会使用一个集合来保持 COMMAND 的顺序,以便您可以执行撤消/重做/任何操作。

采纳答案by Jon Skeet

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:

明确地说,订阅事件处理程序仅意味着调用事件的适当“添加”部分。如果事件通过执行以下操作来处理此问题:

myHandler += value;

that gets translated into

被翻译成

myHandler = Delegate.Combine(myHandler, value);

and Delegate.Combineguarantees the ordering. However, if you had an event like this:

Delegate.Combine保证排序。但是,如果您有这样的事件:

private LinkedList<EventHandler> eventHandlers = new LinkedList<EventHandler>;

public event EventHandler Foo
{
    add
    {
        eventHandlers.AddFirst(value);
    }
    remove
    {
        // do stuff here too
    }
}

and then fired the event by doing something like:

然后通过执行以下操作来触发事件:

foreach (EventHandler handler in eventHandlers)
{
    handler(this, EventArgs.Empty);
}

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'tmaintain the appropriate ordering.

摘要:对于所有理智的事件,您可以依赖排序。理论上,事件可以随心所欲,但我从未见过保持适当顺序的事件。

回答by Paul

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.

如果 Two() 依赖于 One() 正在做的事情,那么要么附加一个以正确顺序调用这两个方法的委托,要么在必要时让 Two() 调用 One()。

回答by Steven A. Lowe

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.

密切注意 Jon Skeet 给出的警告——“鉴于该实施......”。换句话说,进行最细微的更改(多线程、其他处理程序等),您就有可能失去执行顺序不变性。

Do NOTrely 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.

我将更进一步,并断言如果您必须假设事件触发的顺序,那么您就有严重的设计缺陷和/或滥用事件。

回答by Trap

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.

Jon Skeet 所说的对于当前实现在技术上是正确的,但在 c#8.5 或 VBasic 15.0 中可能不会。依赖实施细节总是弊大于利。

回答by supercat

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.

然而,在某些情况下,事件可能用于此类排序很重要的上下文中。事件处理程序可以传递一个可变对象,并期望利用该对象的先前处理程序的更改。在这种情况下,如果事件的有意义的操作需要它们以特定的顺序执行,并且假设订阅者的任何文档要求都得到遵守,那么人们应该期望事件将按照给定的顺序执行。