Лови все исключения и ничего не делай? - PullRequest
3 голосов
/ 01 марта 2011

Я только что унаследовал код, имеющий более 300 случаев этого:

catch(Exception ex)
{
    string s = ex.Message ;
}

Когда я в следующий раз столкнусь с человеком, который написал это, что мне с ним делать?

А если серьезно ...

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

Это приложение WinForms, которое внутри моей организации запускают около двух десятков пользователей.

Ответы [ 10 ]

5 голосов
/ 01 марта 2011

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

5 голосов
/ 01 марта 2011

Вы можете удалить все эти блоки catch и добавить следующий код перед запуском вашей первой формы:

public static void Main(string[] args)
{
// Event handler for handling UI thread exceptions.
Application.ThreadException += 
    new ThreadExceptionEventHandler(App_UiThreadException);

// Force all Windows Forms errors to go through our handler.
// NB In .NET 4, this doesn't apply when the process state is corrupted.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// Event handler for handling non-UI thread exceptions. 
AppDomain.CurrentDomain.UnhandledException += new 
    UnhandledExceptionEventHandler(App_NonUiThreadException);

// Run the application.
}

Перехват всех событий

Вызов SetUnhandledExceptionMode гарантирует, что все необработанные исключения будут перехвачены независимо от параметров конфигурации приложения.

Обратите внимание, что начиная с .NET Framework 4 события, закодированные выше и обсуждаемые ниже, не генерируются для исключений, которые повреждают состояниепроцесса, например переполнения стека или нарушения прав доступа - если обработчик событий не критичен к безопасности и не имеет атрибута HandleProcessCorruptedStateExceptionsAttribute .

В имеется интересная запись об исключениях, которыеповреждено состояние процесса .

Исключения потока пользовательского интерфейса

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

Исключения потоков не-пользовательского интерфейса

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

3 голосов
/ 01 марта 2011

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

Почему этот загадочный подход?

  1. Автор не знал, что вы можете настроить отладчик на разрыв при возникновении исключения ( CTRL + ALT + E в Visual Studio)
  2. Если вы отлаживаете иперехватить исключение в пустом обработчике перехвата, трудно перейти к оператору, который позволяет вам получить доступ к области действия обработчика и сообщению об исключении (вам нужно знать, чтобы поставить точку останова на закрывающей скобке)

Я не удивлюсь, если приложение будет работать без обработчиков исключений no-op;Я бы удалил их и добавил бы механизм регистрации верхнего уровня для записи необработанных исключений, как предлагали другие.Если через журналы вы обнаружите, что необработанное исключение может быть обработано, то у вас будет свой стек вызовов и вы узнаете, где ввести соответствующий обработчик.

3 голосов
/ 01 марта 2011

Представьте механизм регистрации и, по крайней мере, регистрируйте эти сообщения об ошибках!

2 голосов
/ 01 марта 2011

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

catch(Exception ex) {
  throw;
}

Если вы просто удалите все блоки try ... catch, вы сможетевозникли проблемы с областями видимости при удалении блока контекста для всего кода в каждой попытке ... поймать.Просто отправив их в исходное состояние, вы сможете увидеть, где часто возникают ошибки, и вы можете их исправить.Затем позже вы можете добавить надлежащую обработку исключений и / или ведение журналов, где это необходимо, и удалить блоки try ... catch, если они бесполезны.

2 голосов
/ 01 марта 2011

Я бы добавил протоколирование, чтобы оценить его в производстве, и перебросил в dev - чтобы понять проблемы:

LogCrazyException(ex);
#if DEBUG
    throw;
#endif
1 голос
/ 01 марта 2011

Я бы удалил их все, кроме тех, которые находятся на верхнем уровне обработчика событий.На этом уровне я бы отображал MessageBox, содержащий информацию об исключении.

0 голосов
/ 20 декабря 2012
try{

}
catch (Exception)
{
}

предотвратит появление предупреждающих сообщений

0 голосов
/ 01 марта 2011

В некоторых случаях уместно поймать исключение и ничего не делать. Например, при вызове Control.BeginInvoke для запроса на обновление самого элемента управления индикатора выполнения, возникает неизбежное (*) состояние гонки, если какой-то другой поток может располагать элементом управления. Хотя, возможно, следует отлавливать только те исключения, которые можно ожидать от BeginInvoke, существует философский аргумент, который гласит, что любые условия, которые могут вызвать BeginInvoke, могут представлять интерес для потока пользовательского интерфейса, но на самом деле не представляют интереса для работника. поток, который пытается предоставить уведомление об обновлении вежливости. Все исключения из BeginInvoke, которые система разрешает перехватывать, не должны влиять на рабочий поток, а те, которые не могут быть перехвачены, не будут перехвачены. На самом деле нет никаких причин, по которым исключения, связанные с пользовательским интерфейсом, должны выходить из подпрограммы, целью которой не является обновление пользовательского интерфейса, а вместо этого предполагается выполнение бизнес-логики (с обновлениями индикатора выполнения как побочным эффектом вежливости).

Все это, как говорится, 300 раз звучит как слишком много для паттерна Try-Catch-Ignore. Если их много, например Операторы BeginInvoke, заключенные в такие блоки catch, должны быть извлечены в другую подпрограмму TryBeginInvoke. Аналогично, если есть много вызовов какой-либо другой функции, которая возвращает исключение «ничего не делать». Хотя я могу представить, что всего может быть 300 обращений к нескольким функциям, которые возвращают такие неприятные исключения, я сомневаюсь, что есть 300 таких функций.

(*) Можно было бы использовать блокировки для защиты методов BeginInvoke и Dispose, но это добавляет значительную сложность и создает дополнительные возможности для того, чтобы что-то пошло не так. Если бы существовал метод .net TryBeginInvoke, это было бы прекрасно. Так как он не существует, написание такой подпрограммы для переноса BeginInvoke с блоком Try-Catch-Ignore кажется наилучшим подходом.

0 голосов
/ 01 марта 2011

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

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