Как обработать исключение в многоадресном делегате в C #? - PullRequest
4 голосов
/ 21 апреля 2011

Мне дали код, который я вызываю через многоадресный делегат.

Я хотел бы знать, как я могу отследить и обработать любое возникшее там исключение, которое пока не управляется. Я не могу изменить данный код.

Я искал вокруг и обнаружил необходимость вызова GetInvocationList (), но не совсем уверен, полезно ли это.

Ответы [ 3 ]

4 голосов
/ 21 апреля 2011

Рассмотрим код, используя GetInvocationList:

foreach (var handler in theEvent.GetInvocationList().Cast<TheEventHandler>()) {
   // handler is then of the TheEventHandler type
   try {
      handler(sender, ...);
   } catch (Exception ex) {
      // uck
   }
}   

Это мой старый подход, более новый подход, который я предпочитаю выше, потому что он упрощает вызов, включая использование параметров out / ref (если желательно).

foreach (var singleDelegate in theEvent.GetInvocationList()) {
   try {
      singleDelgate.DynamicInvoke(new object[] { sender, eventArg });
   } catch (Exception ex) {
      // uck
   }
}

, который по отдельности вызывает каждого делегата, который был бы вызван с

 theEvent.Invoke(sender, eventArg)

Удачного кодирования.


Не забудьте выполнить стандартную проверку на отсутствие защиты (и, возможно, блокировку) при работе с событиями.

2 голосов
/ 21 апреля 2011

Вы можете пройтись по всем делегатам, зарегистрированным в списке многоадресной рассылки, и вызывать каждого из них по очереди, оборачивая каждый вызов в блок try - catch.

В противном случае вызовы последующих делегатов в многоадресной рассылке после делегата с исключением будут прерваны.

0 голосов
/ 17 февраля 2016

Ответ с поправкой предназначен для событий, для делегатов специально попробуйте этот метод расширения:

    public static class DelegateExtensions
{
    public static void SafeInvoke(this Delegate del,params object[] args)
    {
        foreach (var handler in del.GetInvocationList())
        {
            try
            {
                    handler.Method.Invoke(handler.Target, args);
            }
            catch (Exception ex)
            {
                // ignored
            }
        }
    }
}
...