事件处理程序是否按照它们附加到事件的顺序触发?如果没有,我可以在事件处理程序上强制执行某种顺序,以便按特定顺序调用它们吗?
答案 0 :(得分:18)
假设事件的简单实现(在委托字段上使用+ =和 - =,然后使用Delegate.Combine/Remove
)然后是,则将按照它们的顺序调用事件处理程序认购。保证在Delegate.Combine
文档中有效地给出:
返回值
新的多播(可组合)委托 有一个调用列表 连接 a 的调用列表 和 b 按此顺序。
请参阅我的article about events,了解Delegate.Combine/Remove
做的一些示例(以及幕后的事件)。
答案 1 :(得分:4)
NOT 依赖于事件排序。所有事件调度都应该在逻辑上独立,就好像它们是并行发生的一样。
在其他类和线程中添加事件处理程序可能会干扰您的假设排序,这不是一个安全的假设,它违背了事件的概念作为独立的解耦操作。
我会更进一步,断言如果你必须承担一个事件发生的命令,你就会有严重的设计缺陷和/或滥用事件。
答案 2 :(得分:2)
您可能有一个事件处理程序以指定的顺序调用其他函数或委托。
答案 3 :(得分:2)
我建议“包装它。”
做这样的事......
MyObject.MyEvent += new MyEventHandler(Wrapper);
public void Wrapper()
{
Method1();
Method3();
Method2();
}
通过这种方式,你仍然可以挂钩事件,但可以完全控制所谓的事件。
答案 4 :(得分:0)
很抱歉迟到的回复。
我遇到过一种情况,我必须处理事件处理程序的顺序。
我有一个表单,当我单击表单上的一个按钮时,会在我的代码中的某个位置添加一个对象。
该集合有一个“已添加”事件,并且两个代表已被挂钩。其中一个方法删除刚刚添加到集合中的任何项目,而另一个方法则向用户显示消息。
如果我在这里显示了一些代码,则在触发事件时会抛出“IndexOutOfRange”异常:
// this methods hooks two delegates to MyCollection.Added event, but the order results in a "IndexOutOfRange" exception after the event is triggered
HookEvents()
{
MyCollection.Added += new CollectionItemAddedHandler(DeleteItem_After_CollectionItemAdded);
MyCollection.Added += new CollectionItemAddedHandler(ShowMessage_After_CollectionItemAdded);
}
// when user click a button on form, add a object to MyCollection
Button_Clicked()
{
MyCollection.Add(new object());
}
// at the moment a object is added into the collection, this method remove it
DeleteItem_After_CollectionItemAdded(NewIndexArgs e)
{
MyCollection.Remove(e.NewIndex); // e.NewIndex represents the newly added item index in current collection
}
// at the moment a object is added into the collection, this method show its information (hey, but remember, I just remove it in the previous method)
ShowMessage_After_CollectionItemAdded(NewIndexArgs e)
{
MessageBox.Show(MyCollection[e.NewIndex]); // tell user what is just added into the current collection
// a "IndexOutOfRange" exception is thrown here....
}
使此方案正常工作正确的原因是“ShowMessage_After_CollectionItemAdded”方法应该先触发 ,然后才能成为“DeleteItem_After_CollectionAdded”方法。
虽然我们首先可以+ =“ShowMessage ...”方法,但有时我们无法在运行时之前预定义此序列。