C# 事件处理程序执行顺序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1645478/
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
Order of event handler execution
提问by Phillip Ngan
If I set up multiple event handlers, like so:
如果我设置多个事件处理程序,如下所示:
_webservice.RetrieveDataCompleted += ProcessData1;
_webservice.RetrieveDataCompleted += ProcessData2;
what order are the handlers run when the event RetrieveDataCompleted
is fired? Are they run in the same thread and sequentially in the order that are registered?
RetrieveDataCompleted
触发事件时处理程序的运行顺序是什么?它们是否在同一个线程中按注册的顺序依次运行?
采纳答案by Reed Copsey
Currently, they are executed in the order they are registered. However, this is an implementation detail, and I would not rely on this behavior staying the same in future versions, since it is not required by specifications.
目前,它们按照注册的顺序执行。但是,这是一个实现细节,我不会依赖这种行为在未来版本中保持不变,因为规范不需要它。
回答by Bob
They are run in the order in which they are registered. RetrieveDataCompleted
is a Multicast Delegates. I am looking through reflector to try and verify, and it looks like an array is used behind the scenes to keep track of everything.
它们按照注册的顺序运行。RetrieveDataCompleted
是一个Multicast Delegates。我正在查看反射器以尝试验证,看起来在幕后使用了一个数组来跟踪所有内容。
回答by Rex M
The order is arbitrary. You cannot rely on the handlers being executed in any particular order from one invocation to the next.
顺序是任意的。您不能依赖从一次调用到下一次调用以任何特定顺序执行的处理程序。
Edit:And also - unless this is just out of curiosity - the fact that you need to know is indicative of a seriousdesign problem.
编辑:而且 - 除非这只是出于好奇 - 您需要知道的事实表明存在严重的设计问题。
回答by Philip Wallace
The invocation list of a delegate is an ordered set of delegates in which each element of the list invokes exactly one of the methods invoked by the delegate. An invocation list can contain duplicate methods. During an invocation, a delegate invokes methods in the order in which they appear in the invocation list.
委托的调用列表是一组有序的委托,其中列表的每个元素都调用委托调用的方法之一。调用列表可以包含重复的方法。在调用期间,委托按方法在调用列表中出现的顺序调用方法。
From here: Delegate Class
从这里: 代表类
回答by Naser Asadi
You can change ordering by detaching all handlers, and then re-attaching in desired order.
您可以通过分离所有处理程序,然后按所需顺序重新附加来更改顺序。
public event EventHandler event1;
public void ChangeHandlersOrdering()
{
if (event1 != null)
{
List<EventHandler> invocationList = event1.GetInvocationList()
.OfType<EventHandler>()
.ToList();
foreach (var handler in invocationList)
{
event1 -= handler;
}
//Change ordering now, for example in reverese order as follows
for (int i = invocationList.Count - 1; i >= 0; i--)
{
event1 += invocationList[i];
}
}
}
回答by Fábio Augusto Pandolfo
If someone need to do this in the context of a System.Windows.Forms.Form, here is an example inverting the order of Shown event.
如果有人需要在 System.Windows.Forms.Form 的上下文中执行此操作,这里是一个反转 Shown 事件顺序的示例。
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
namespace ConsoleApplication {
class Program {
static void Main() {
Form form;
form = createForm();
form.ShowDialog();
form = createForm();
invertShownOrder(form);
form.ShowDialog();
}
static Form createForm() {
var form = new Form();
form.Shown += (sender, args) => { Console.WriteLine("form_Shown1"); };
form.Shown += (sender, args) => { Console.WriteLine("form_Shown2"); };
return form;
}
static void invertShownOrder(Form form) {
var events = typeof(Form)
.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(form, null) as EventHandlerList;
var shownEventKey = typeof(Form)
.GetField("EVENT_SHOWN", BindingFlags.NonPublic | BindingFlags.Static)
.GetValue(form);
var shownEventHandler = events[shownEventKey] as EventHandler;
if (shownEventHandler != null) {
var invocationList = shownEventHandler
.GetInvocationList()
.OfType<EventHandler>()
.ToList();
foreach (var handler in invocationList) {
events.RemoveHandler(shownEventKey, handler);
}
for (int i = invocationList.Count - 1; i >= 0; i--) {
events.AddHandler(shownEventKey, invocationList[i]);
}
}
}
}
}
回答by Rahul
A MulticastDelegate has a linked list of delegates, called an invocation list, consisting of one or more elements. When a multicast delegate is invoked, the delegates in the invocation list are called synchronously in the order in which they appear. If an error occurs during execution of the list then an exception is thrown.
MulticastDelegate 有一个委托链表,称为调用列表,由一个或多个元素组成。当调用多播委托时,调用列表中的委托将按照它们出现的顺序同步调用。如果在执行列表期间发生错误,则会引发异常。
回答by ruslanu
During an invocation, methods are invoked in the order in which they appear in the invocation list.
在调用期间,方法按照它们在调用列表中出现的顺序被调用。
But nobody says that invocation list maintain delegates in the same order as they are added. Thus invocation order is not guaranteed.
但是没有人说调用列表以与添加相同的顺序维护委托。因此不能保证调用顺序。
回答by Bill
I had a similar problem. In my case it was fixed very easily. I'd never seen a delegate that didn't use the += operator. My problem was fixed by having one delegate always added at the end, all the others are always added at the beginning. The OP's example would be something like:
我有一个类似的问题。就我而言,它很容易修复。我从未见过不使用 += 运算符的委托。我的问题是通过在最后添加一个代表来解决的,所有其他代表总是在开始时添加。OP 的示例类似于:
_webservice.RetrieveDataCompleted = _webservice.RetrieveDataCompleted + ProcessData1;
_webservice.RetrieveDataCompleted = ProcessData2 + _webservice.RetrieveDataCompleted;
In the first case ProcessData1 will be called last. In the 2nd case ProcessData2 will be called first.
在第一种情况下 ProcessData1 将最后调用。在第二种情况下,将首先调用 ProcessData2。