[c#] 이벤트 핸들러 실행 순서

다음과 같이 여러 이벤트 핸들러를 설정하면 :

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

이벤트 RetrieveDataCompleted가 시작될 때 핸들러는 어떤 순서로 실행 됩니까? 동일한 스레드에서 등록 된 순서대로 순차적으로 실행됩니까?



답변

현재 등록 된 순서대로 실행됩니다. 그러나 이것은 구현 세부 사항이며 사양에 필요하지 않으므로 향후 버전에서 동일하게 유지되는이 동작에 의존하지 않을 것입니다.


답변

대리자의 호출 목록은 목록의 각 요소가 대리자가 호출 한 메서드 중 정확히 하나를 호출하는 순서가 지정된 대리자 집합입니다. 호출 목록에는 중복 메소드가 포함될 수 있습니다. 호출 중에 델리게이트는 호출 목록에 나타나는 순서대로 메서드를 호출합니다 .

여기에서 :
Delegate Class


답변

모든 핸들러를 분리 한 다음 원하는 순서로 다시 연결하여 순서를 변경할 수 있습니다.

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


답변

순서는 임의적입니다. 하나의 호출에서 다음 호출까지 특정 순서로 실행되는 핸들러에 의존 할 수 없습니다.

편집 : 또한-이것이 호기심에서 벗어나지 않는 한-알아야 할 사실은 심각한 디자인 문제를 나타냅니다 .


답변

등록 된 순서대로 실행됩니다. RetrieveDataCompletedA는 멀티 캐스트 대표 . 나는 반사경을 통해 확인하고 시도하고 있으며 모든 것을 추적하기 위해 배후에서 배열이 사용되는 것처럼 보입니다.


답변

누군가 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에는 하나 이상의 요소로 구성된 호출 목록이라고하는 델리게이트 연결 목록이 있습니다. 멀티 캐스트 대리자가 호출되면 호출 목록의 대리자가 나타나는 순서대로 동 기적으로 호출됩니다. 목록 실행 중에 오류가 발생하면 예외가 발생합니다.