WPF Exception Viewer

Сложность 100-200

Достаточно давно я писал о том, как работать (обрабатывать) с исключениями при использовании класса Task из Task Parallel Library (TPL), все описанные способы действительно работают и проверены на практике уже много раз и отлично меня спасают и упорядочивают работу с потоками, особенно с получением исключений. Однако тогда я упустил важный момент как еще централизованно можно получать исключения и никак не был освещен вопрос удобства работы с исключениями: отображение и коммуникация от пользователя. Сегодня собираюсь наверстать упущенное тем более под руку подвернулся удобный и простой набросок от MarkLTX с CodeProject.

Как оно бывает обычно

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

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

Следующей проблемой является то, что сообщение об ошибке вываливается огромной простыней порой. Не так все страшно, когда это происходит у разработчиков, так как известно, что фокус стоит на кнопке «ОК», но пользователи этого не знаю и входят в ступор.

Так же пользователи не знаю, что текст можно копировать нажав Ctrl+C и высылают FullHD скриншот с ошибкой. Конечно весело порой посмотреть на чужие рабочие столы, но это быстро надоедает.

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

Пока оставим разговор на тему: «показывать пользователю картинку в духе

И писать мол разработчики уже знаю об ошибке и приступили к ее расследованию/исправлению.»

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

В качестве резюме об обычном отображении ошибки:

  • Экран ошибки может закрывать все на мониторе. Особенно при низких разрешениях или же длинном стеке сообщений, так как пользователь может не увидеть кнопку «ОК» и запаниковать.
  • Неочевидно для пользователя как скопировать текст ошибки и шлют все картинкой.
  • Необходимо «раскручивать» вложенные ошибки.
  • Сообщения высылаются в виде картинок, что неудобно (траффик, дисковое место).

В качестве альтернативы я нашел упомянутый в заголовке компонент.

 WPF Exception Viewer

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

На мой взгляд очень симпатично и практично! Пример того, что и как помещается в буфер обмена приводить не буду, но с форматированием сообщения проблем нет, что приятно удивило.

Пользоваться данным компонентом очень просто.  Специально для вас я оформил это в виде NuGet пакета, который можно поставить с помощью команды:

PM> Install-Package WpfExceptionViewer

После чего можно использовать класс ExceptionViewer(), передав в качестве параметра заголовок окна и само исключение.

Все очень просто!

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

Получение ошибок от класса Task

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

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

И если выбрасывать исключение следующим образом:

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

В этом случае будет все как ожидается.

Для освежения памяти рекомендую перечитать статью «Обработка исключений при работе с классом Task».

 

Итого

Настоятельно рекомендую ознакомится с данным компонентом, с исходным кодом (если интересно), попробовать компонент в деле, тем более что установить и попробовать его с помощью NuGet дело всего нескольких минут. Кстати, компонент в NuGet собран для .Net Framework 4.0 и имеет строгую подпись.

 

Hard’n’Heavy!

 

 

Оставить комментарий