it-swarm.com.de

Reihenfolge der Ausführung des Ereignishandlers

Wenn ich mehrere Event-Handler einrichte:

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

in welcher Reihenfolge werden die Handler ausgeführt, wenn das Ereignis RetrieveDataCompleted ausgelöst wird? Werden sie im selben Thread und nacheinander in der Reihenfolge ausgeführt, in der sie registriert sind?

72
Phillip Ngan

Derzeit werden sie in der Reihenfolge ausgeführt, in der sie registriert sind. Dies ist jedoch ein Implementierungsdetail, und ich würde mich nicht darauf verlassen, dass dieses Verhalten in zukünftigen Versionen gleich bleibt, da es von den Spezifikationen nicht verlangt wird.

111
Reed Copsey

Die Aufrufliste eines Delegaten lautet eine geordnete Gruppe von Delegierten, in denen Jedes Element der Liste ruft .__ auf. genau eine der Methoden, die von .__ aufgerufen werden. der Delegierte Eine Aufrufliste kann enthalten doppelte Methoden. Während eines Aufruf, ein Delegat ruft die Methoden auf in der Reihenfolge, in der sie in .__ erscheinen. die Aufrufliste.

Von hier aus: Klasse delegieren

48
Philip Wallace

Sie können die Reihenfolge ändern, indem Sie alle Handler entfernen und in der gewünschten Reihenfolge erneut anfügen.

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];
        }
    }
}
9
Naser Asadi

Sie werden in der Reihenfolge ausgeführt, in der sie registriert sind. RetrieveDataCompleted ist ein Multicast-Delegierter . Ich schaue durch Reflektor, um zu versuchen und zu überprüfen, und es sieht aus, als würde ein Array hinter den Kulissen verwendet, um den Überblick zu behalten. 

8
Bob

Die Reihenfolge ist beliebig. Sie können sich nicht darauf verlassen, dass die Handler in einer bestimmten Reihenfolge von Aufruf zu Aufruf ausgeführt werden.

Edit: Und außerdem - sofern dies nicht aus Neugierde ist - zeigt die Tatsache, dass Sie es wissen müssen, ein ernstes Designproblem an.

8
Rex M

Ein MulticastDelegate verfügt über eine verknüpfte Liste von Delegierten, eine Aufrufliste, die aus einem oder mehreren Elementen besteht. Wenn ein Multicast-Delegat aufgerufen wird, werden die Delegaten in der Aufrufliste synchron in der Reihenfolge aufgerufen, in der sie angezeigt werden. Wenn während der Ausführung der Liste ein Fehler auftritt, wird eine Ausnahme ausgelöst.

2
Rahul

Wenn jemand dies im Zusammenhang mit einem System.Windows.Forms.Form tun muss, ist hier ein Beispiel, in dem die Reihenfolge des angezeigten Ereignisses umgekehrt wird.

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

Während eines Aufrufs werden Methoden in der Reihenfolge aufgerufen, in der sie in der Aufrufliste angezeigt werden.

Niemand sagt jedoch, dass die Aufrufliste die Delegaten in der Reihenfolge hält, in der sie hinzugefügt werden .. Die Aufrufreihenfolge ist daher nicht garantiert.

0
ruslanu