事件处理程序执行的顺序

如果我设置了多个事件处理程序,如下所示:

_webservice.RetrieveDataCompleted += ProcessData1; _webservice.RetrieveDataCompleted += ProcessData2; 

当事件RetrieveDataCompleted被触发时,处理程序运行的顺序是什么? 他们在同一个线程中运行,并按照已注册的顺序运行?

目前,它们是按照他们注册的顺序执行的。 但是,这是一个实现细节,我不会依赖这种行为在未来版本中保持不变,因为它不是规范所要求的。

委托的调用列表是一组有序的委托,其中列表的每个元素都只是调用由委托调用的一个方法。 调用列表可以包含重复的方法。 在调用期间, 委托会按照它们在调用列表中出现的顺序调用方法

从这里: 委托类

顺序是任意的。 您不能依靠从一个调用到下一个调用的特定顺序执行处理程序。

编辑:而且 – 除非这只是出于好奇 – 你需要知道的事实是一个严重的devise问题的指示。

他们按照他们注册的顺序运行。 RetrieveDataCompleted是一个多播代表 。 我正在通过reflection器来查看并validation,看起来像是在幕后使用数组来跟踪一切。

您可以通过分离所有处理程序来更改顺序,然后按照所需顺序重新连接。

 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]; } } } 

如果有人需要在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]); } } } } } 

MulticastDelegate有一个委托的链表,称为调用列表,由一个或多个元素组成。 在调用多播委托时,调用列表中的委托按其出现的顺序同步调用。 如果在执行列表过程中发生错误,则会引发exception。