Ordem de execução do manipulador de events

Se eu configurar vários manipuladores de events, assim:

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

Que ordem os manipuladores executam quando o evento RetrieveDataCompleted é triggersdo? Eles são executados no mesmo thread e seqüencialmente na ordem em que são registrados?

Atualmente, eles são executados na ordem em que são registrados. No entanto, esse é um detalhe de implementação, e eu não confiaria que esse comportamento permanecesse o mesmo em versões futuras, uma vez que não é exigido pelas especificações.

A lista de invocação de um delegado é um conjunto ordenado de representantes no qual cada elemento da lista invoca exatamente um dos methods invocados pelo delegado. Uma lista de invocação pode conter methods duplicados. Durante uma chamada, um delegado invoca methods na ordem em que eles aparecem na lista de invocação .

Daqui: Classe de Delegado

A ordem é arbitrária. Você não pode confiar nos manipuladores que estão sendo executados em qualquer ordem específica de uma invocação para a próxima.

Edit: E também – a menos que isso seja apenas por curiosidade – o fato de que você precisa saber é indicativo de um grave problema de design.

Você pode alterar a ordem desanexando todos os manipuladores e, em seguida, anexando novamente na ordem desejada.

 public event EventHandler event1; public void ChangeHandlersOrdering() { if (event1 != null) { List invocationList = event1.GetInvocationList() .OfType() .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]; } } } 

Eles são executados na ordem em que são registrados. RetrieveDataCompleted é um delegado multicast . Eu estou olhando através do refletor para tentar verificar, e parece que uma matriz é usada nos bastidores para acompanhar tudo.

Se alguém precisar fazer isso no contexto de um System.Windows.Forms.Form, aqui está um exemplo invertendo a ordem do evento mostrado.

 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() .ToList(); foreach (var handler in invocationList) { events.RemoveHandler(shownEventKey, handler); } for (int i = invocationList.Count - 1; i >= 0; i--) { events.AddHandler(shownEventKey, invocationList[i]); } } } } } 

Um MulticastDelegate possui uma linked list de representantes, chamada de lista de invocação, consistindo em um ou mais elementos. Quando um delegado multicast é invocado, os delegates na lista de invocação são chamados de forma síncrona na ordem em que aparecem. Se ocorrer um erro durante a execução da lista, uma exceção será lançada.