Перехват ошибок C # на уровне библиотеки классов - PullRequest
1 голос
/ 06 мая 2011

Я пытаюсь найти решение для регистрации ошибок для библиотеки классов корпоративного уровня.Некоторые из требований:

  • Он будет использоваться несколькими конечными приложениями (следовательно, поэтому он должен обрабатываться в библиотеках классов)
  • Он должен погружать свои данные в SQL ServerБаза данных для удобного хранения.Это также относится и к третьему:
  • Он должен поддерживать пользовательское веб-приложение, считывающее его данные.

Есть еще одно требование, которое очень приятно иметь».То есть это не критично, но если это неосуществимо, у меня должна быть чертовски веская причина для этого.

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

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

Ответы [ 3 ]

4 голосов
/ 06 мая 2011

Если вы хотите перехватить все необработанные исключения, не происходящие из вашего собственного стека вызовов, вы можете изучить использование объекта AppDomain :

AppDomain.CurrentDomain.UnhandledException += (s, e) => {
    // Your logging logic
};

AppDomain.CurrentDomain.FirstChanceException += (s, e) => {
    // Your logging logic
};
1 голос
/ 06 мая 2011

Когда я читаю библиотеку классов корпоративного уровня, у меня возникает следующее требование:

  • Ваш компонент не должен создавать исключений и нарушать работу системы.
  • Он должен корректно обрабатывать ошибки и иметь возможность восстанавливаться после ошибок.

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

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

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

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

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

Но во время выполнения ваша библиотека классов использует

  • Реальная физическая память (OutOfMemoryException)
  • Реальное пространство на жестком диске (по крайней мере, файлы журналов) (жесткий диск заполнен)
  • Реальные циклы ЦП (100% ЦП)
  • Пространство реального стека (StackOverFlowException)

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

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

Это было сказано, я надеюсь, что вы спрашивали не о том, как перехватить все ошибки на уровне библиотеки классов, а в ваших конечных приложениях, где вы отображаете ошибки для пользователя и регистрируете их (надеюсь, только один раз и не снова на каждом слое, потому что вы не доверяйте другим слоям). Как уже отмечали другие, вы можете получить в свои руки необработанные исключения, которые прервали поток, который, в свою очередь, прервет ваш процесс, когда ваш обработчик ошибок останется. Помимо этого, неплохо бы поместить блок try / catch вокруг метода Main, чтобы перехватывать ошибки в основном потоке. Если ваше приложение имеет пользовательский интерфейс (Windows Forms), вам также следует зарегистрироваться в событии Application.ThreadException, которое будет вызываться, когда исключение распространяется из обработчика сообщений Window.

С уважением, Алоис Краус

1 голос
/ 06 мая 2011

Похоже, здесь может быть полезна Microsoft Enterprise Library ...

http://msdn.microsoft.com/en-us/library/ff649552.aspx

...