C # SmtpClient.Send () - Любая альтернатива (или компаньон) для обработки исключения? - PullRequest
2 голосов
/ 10 июля 2009

(Долгое время читатель SO, впервые спрашивающий q.

Я довольно новичок в C #, уже много лет в мире PHP / Ruby / Python, поэтому прошу прощения, если это глупый вопрос.)

Я занимаюсь некоторым обслуживанием старого приложения на C #, которое вылетает при сбое SmtpClient.Send (). Из того, что я почерпнул из MSDN, я вижу очевидный способ исправить это, но мой вопрос также касается более общего случая.

Согласно MSDN:

  try {
          client.Send(message);
  }  
  catch (Exception ex) {
          Console.WriteLine("Exception caught in CreateTestMessage2(): {0}", 
                ex.ToString() );
  }

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

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

Опять извините, если это дерьмовый вопрос. Я пытался искать в SO и Google столько, сколько мог.

РЕДАКТИРОВАТЬ: Я только что нашел этот вопрос Лучшие практики для управления исключениями в Java или C что вполне может дать ответ на мой вопрос.

EDIT2: Спасибо за оперативную обратную связь, невероятно быстро. Я немного больше думал о проблеме, и, возможно, это могло бы еще больше уточнить то, что я спрашиваю.

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

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

Ответы [ 5 ]

4 голосов
/ 10 июля 2009

Это хороший пример того, что я называю «экзогенной» исключительной ситуацией.

http://ericlippert.com/2008/09/10/vexing-exceptions/

Рассмотрим аналогичный случай - открытие файла. Вы можете уменьшить вероятность получения исключения на:

  • проверка наличия файла
  • проверка, есть ли у пользователя разрешение на открытие файла
  • проверка блокировки файла другим приложением
  • ли
  • бла-бла
  • бла-бла-бла

Вы можете сделать все это, и ВСЕГДА получите исключение при открытии файла. Потому что между выполнением всех этих проверок и попыткой открыть файл что-то могло измениться. Другой процесс мог изменить разрешения или заблокировать файл, или пользователь удалил компакт-диск из привода или что-то еще. Успешное действие или нет, основано на экзогенных, реальных условиях, которые вы не можете проверить каким-либо гарантированным способом.

Экзогенные исключения - это боль, с которой приходится иметь дело, потому что вам НЕОБХОДИМО разобраться с ними, даже если вы проделали большую работу по их устранению.

Отправка почты осуществляется аналогичным образом. Вы можете проверить все виды вещей, чтобы попытаться устранить исключение, которое, вероятно, будет работать в 99% случаев, но вы все еще не можете ГАРАНТИРОВАТЬ, что между всеми вашими проверками и фактической попыткой отправки почты, что кто-то не отключил маршрутизатор в самый неподходящий момент. Вам просто придется смириться с этим и обработать исключения.

3 голосов
/ 10 июля 2009

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

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

Мой общий совет: отлавливайте конкретные исключения как можно ближе к источнику, позвольте остальным пузыриться в стеке и регистрировать его в точке, где у вас достаточно контекста, чтобы позже попытаться воспроизвести исключение. Будьте осторожны, что ловля и повторная броска обходятся дорого; Сценарий в вашем примере, где вы можете захотеть сделать это, будет, если, скажем, SmtpException был тайм-аут соединения (я делаю это), то одна стратегия может быть экспоненциально отменить и повторить до n раз с момента отправки почты сервер может быть недоступен, а затем, в конце концов, сдаться и сбросить, если вам это не удастся.

Действительно короткий ответ: все зависит.

1 голос
/ 10 июля 2009

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

1 голос
/ 10 июля 2009

При чтении MSDN вы можете увидеть список исключений, выданных методом .Send (), и сокращенные причины, по которым они будут выброшены. Проверка их и обработка перед вызовом Send () может помочь избежать их, но документация не обязательно охватывает все возможные исключения или причины, по которым они могут возникнуть.

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

0 голосов
/ 10 июля 2009

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

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

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