Возбуждение событий в C #, которые игнорируют исключения, вызванные обработчиками - PullRequest
9 голосов
/ 25 июня 2010

Одной из моих любимых мозолей при возбуждении событий в C # является тот факт, что исключение в обработчике событий нарушит мой код и, возможно, предотвратит вызов других обработчиков, если аварийный вызов был вызван первым;В большинстве случаев мой код не заботился о том, что чей-то другой код, который прослушивает его события, не работает.

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

public static void Raise(this EventHandler eh, object sender, EventArgs e)
{
  if (eh == null)
    return;
  try
  {
    eh(sender, e);
  }
  catch { }
}

Хотя это действительно означаетМой код выполняется независимо, этот метод не останавливает первый обработчик события, генерирующий исключение и предотвращающий уведомление второго и последующих обработчиков о событии.Я ищу способ итерации через GetInvocationList, чтобы обернуть каждый отдельный обработчик событий в свой собственный try / catch, но это кажется неэффективным, и я не уверен в лучшем способе сделать это, или даже если так и должно быть.

Кроме того, мне действительно неудобно просто игнорировать исключение здесь (и ни FxCop / Resharper в этом отношении);реально что должно случиться с исключением в этом случае?

Ответы [ 4 ]

3 голосов
/ 25 июня 2010

Если обработчик события не перехватил исключение, я не вижу хорошего способа обработать исключение в классе, генерирующем событие.У вас нет контекста, чтобы узнать, что делает обработчик.В этом случае безопаснее всего позволить приложению сбоить, так как вы не знаете, какие побочные эффекты мог вызвать другой обработчик событий, что могло бы дестабилизировать ваше приложение.Урок здесь заключается в том, что обработчики событий должны быть устойчивыми (обрабатывать свои собственные исключения), так как классы, которые запускают события, никогда не должны перехватывать исключения, генерируемые обработчиками.

3 голосов
/ 25 июня 2010

Что если вы сделали что-то подобное?

public static void Raise(this EventHandler eh, object sender, EventArgs e)
{
    if (eh == null)
        return;

    foreach(var handler in eh.GetInvocationList().Cast<EventHandler>())
    {
        try
        {
            handler(sender, e);
        }
        catch { }
    }
}
3 голосов
/ 25 июня 2010

Вы должны ловить только те исключения, которые вы можете обработать. Например, вы можете обращаться к файлу и не иметь достаточных прав. Если вы знаете, что это может происходить время от времени, и все, что должно произойти, это то, что дело зарегистрировано, тогда перехватите только это исключение .

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

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

2 голосов
/ 25 июня 2010

Простое, но важное правило:

Каждый дефект в коде должен быть настолько летальным, насколько это возможно, как можно раньше.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...