代码之家  ›  专栏  ›  技术社区  ›  Phillip Ngan

事件处理程序执行顺序

  •  73
  • Phillip Ngan  · 技术社区  · 16 年前

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

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

    事件发生时处理程序的运行顺序是什么 RetrieveDataCompleted 被解雇了?它们是否在同一线程中运行,并按注册的顺序顺序运行?

    8 回复  |  直到 7 年前
        1
  •  112
  •   Larry    12 年前

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

        2
  •  48
  •   Philip Wallace    16 年前

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

    从这里: Delegate Class

        3
  •  9
  •   Naser Asadi    12 年前

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

    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];
            }
        }
    }
    
        4
  •  8
  •   Bob    16 年前

    它们按注册顺序运行。 RetrieveDataCompleted 是一个 Multicast Delegates . 我正在通过反射镜进行尝试和验证,它看起来像是在幕后使用了一个数组来跟踪所有的事情。

        5
  •  8
  •   Rex M    16 年前

    顺序是任意的。从一次调用到下一次调用,您不能依赖以任何特定顺序执行的处理程序。

    编辑: 而且——除非只是出于好奇——你需要知道的事实表明 严重的 设计问题。

        6
  •  2
  •   Fábio Augusto Pandolfo    10 年前

    如果有人需要在system.windows.forms.form的上下文中执行此操作,下面是一个颠倒所显示事件顺序的示例。

    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]);
                    }
                }
            }
        }
    }
    
        7
  •  2
  •   Rahul    10 年前

    多播委托具有委托的链接列表,称为调用列表,由一个或多个元素组成。当一个多播委托被调用时,调用列表中的委托按照它们出现的顺序被同步调用。如果在执行列表期间发生错误,则会引发异常。

        8
  •  0
  •   ruslanu    7 年前

    在调用期间,方法按照它们在调用列表中出现的顺序被调用。

    但是没有人说调用列表维护委托的顺序与添加委托的顺序相同。 因此不保证调用顺序。