Что лучше всего делать, когда в настольном приложении возникают необработанные исключения?
Я думал о том, чтобы показать сообщение пользователю, чтобы он мог связаться со службой поддержки. Я бы порекомендовал пользователю перезапустить приложение, но не заставлять его. Подобно тому, что обсуждается здесь: ux.stackexchange.com - Как лучше всего обрабатывать неожиданные ошибки приложения?
Проект представляет собой приложение .NET WPF, поэтому описанное предложение может выглядеть следующим образом (обратите внимание, что это упрощенный пример. Возможно, имеет смысл скрывать подробности исключения до тех пор, пока пользователь не нажмет «Показать подробности» и не предоставит некоторую функциональность легко сообщить об ошибке):
public partial class App : Application
{
public App()
{
DispatcherUnhandledException += OnDispatcherUnhandledException;
}
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LogError(e.Exception);
MessageBoxResult result = MessageBox.Show(
$"Please help us fix it and contact support@example.com. Exception details: {e.Exception}" +
"We recommend to restart the application. " +
"Do you want to stop the application now? (Warning: Unsaved data gets lost).",
"Unexpected error occured.", MessageBoxButton.YesNo);
// Setting 'Handled' to 'true' will prevent the application from terminating.
e.Handled = result == MessageBoxResult.No;
}
private void LogError(Exception ex)
{
// Log to a log file...
}
}
В реализации (Команды ViewModels или обработчик событий внешних событий) я бы тогда только поймал конкретное экзогенное исключение и позволил всем остальным исключениям (с головой и неизвестным исключениям) перейти к «Обработчику последней инстанции», описанному выше. Для определения исключений с головой и экзогенными исключениями взгляните на: Эрик Липперт - Исключительные исключения
Имеет ли смысл позволить пользователю решать, следует ли закрыть приложение? Когда приложение завершается, у вас наверняка нет противоречивого состояния ... С другой стороны, пользователь может потерять несохраненные данные или не сможет больше остановить любой запущенный внешний процесс, пока приложение не будет перезапущено.
Или это решение, если вам следует закрыть приложение на необработанные исключения в зависимости от типа приложения, которое вы пишете? Это просто компромисс между «надежностью» и «правильностью», как описано в Code Complete, Second Edition
Чтобы дать вам некоторое представление о том, о каком приложении мы говорим: Приложение в основном используется для управления химическими лабораторными приборами и отображения результатов измерений пользователю. Для этого приложения WPF взаимодействуют с некоторыми службами (локальными и удаленными службами). Приложение WPF не связывается напрямую с инструментами.
источник
Ответы:
Вы должны ожидать, что ваша программа завершит работу по большему количеству причин, чем просто необработанное исключение, такое как сбой питания или другой фоновый процесс, который приводит к сбою всей системы. Поэтому я бы рекомендовал завершить и перезапустить приложение, но с некоторыми мерами, чтобы смягчить последствия такого перезапуска и минимизировать возможную потерю данных .
Начните с анализа следующих пунктов:
Сколько данных действительно может быть потеряно в случае завершения программы?
Насколько серьезна такая потеря для пользователя? Можно ли восстановить потерянные данные менее чем за 5 минут или речь идет о потере рабочего дня?
Сколько усилий нужно для реализации стратегии промежуточного резервного копирования? Не исключайте этого, потому что «пользователь должен будет ввести причину изменения» при обычной операции сохранения, как вы написали в комментарии. Лучше подумайте о чем-то вроде временного файла или состояния, которое может автоматически перезагружаться после сбоя программы. Многие типы производительного программного обеспечения делают это (например, MS Office и LibreOffice имеют функцию «автосохранения» и восстановления после сбоя).
Если данные были неправильными или поврежденными, сможет ли пользователь легко это увидеть (возможно, после перезапуска программы)? Если да, вы можете предложить опцию, позволяющую пользователю сохранять данные (с небольшой вероятностью, что они повреждены), затем принудительно перезапустить, перезагрузить их и позволить пользователю проверить, выглядят ли данные нормально. Не перезаписывайте последнюю версию, которая была сохранена регулярно (вместо записи во временное расположение / файл), чтобы не повредить старую версию.
Если такая стратегия «промежуточного резервного копирования» является разумным вариантом, в конечном итоге зависит от приложения и его архитектуры, а также от характера и структуры задействованных данных. Но если пользователь потеряет менее 10 минут работы, и такой сбой случается один раз в неделю или даже реже, я бы, наверное, не стал слишком много думать об этом.
источник
Это в некоторой степени зависит от приложения, которое вы разрабатываете, но в целом, я бы сказал, что если ваше приложение встречает необработанное исключение, вам нужно прекратить его.
Зачем?
Потому что вы больше не можете быть уверены в состоянии приложения.
Определенно, предоставьте полезное сообщение пользователю, но в конечном итоге вы должны прекратить работу приложения.
Учитывая ваш контекст, я бы определенно хотел, чтобы приложение было прекращено. Вы не хотите, чтобы программное обеспечение, работающее в лаборатории, создавало искаженный вывод, и, поскольку вы не думали обработать исключение, вы не представляете, почему оно было выброшено и что происходит.
источник
Учитывая, что это предназначено для химической лаборатории, и что ваше приложение не контролирует приборы напрямую, а через другие службы:
Принудительное завершение после отображения сообщения. После необработанного исключения ваше приложение находится в неизвестном состоянии. Это может посылать ошибочные команды. Это может даже вызвать носовых демонов . Ошибочная команда потенциально может тратить дорогостоящие реагенты или принести опасность для оборудования или людей .
Но вы можете сделать что-то еще: изящно восстановиться после перезагрузки . Я предполагаю, что ваше приложение не отключает эти фоновые службы при сбое. В этом случае вы можете легко восстановить состояние от них. Или, если у вас больше состояния, подумайте о его сохранении. В хранилище, в котором предусмотрены атомарность и целостность данных (возможно, SQLite?).
Редактировать:
Как указано в комментариях, процесс, которым вы управляете, может потребовать достаточно быстрых изменений, чтобы у пользователя не было времени на реагирование. В этом случае вам следует подумать о перезапуске приложения в дополнение к восстановлению изящного состояния.
источник
Попытка вообще ответить на этот вопрос на верхнем уровне программы не является умной игрой.
Если что-то все время пузырилось, и ни в одной точке архитектуры приложения никто не рассматривал этот случай, у вас нет никаких обобщений, которые вы можете сделать о том, какие действия безопасны или нет.
Таким образом, нет, это определенно не является общепринятым дизайном, позволяющим пользователю выбирать, будет ли приложение восстанавливаться или нет, потому что приложение и разработчики демонстративно не проявили должной осмотрительности, необходимой, чтобы выяснить, возможно ли это или даже целесообразно ,
Однако, если приложение имеет важные части своей логики или поведения, которые были разработаны с учетом такого рода восстановления после сбоев, и возможно использовать их в этом случае, тогда, безусловно, сделайте это - в этом случае , может быть приемлемо предложить пользователю посмотреть, хочет ли он предпринять попытку восстановления, или же он просто хочет, чтобы он завершил работу и начал заново.
Такое восстановление обычно не является необходимым или рекомендуемым для всех (или даже большинства) программ, но, если вы работаете над программой, для которой требуется такая степень операционной целостности, это может быть обстоятельством, при котором представление такого рода подсказка для пользователя была бы вменяемой вещью.
В случае какой-либо особой логики восстановления после сбоя - нет, не делайте этого. Вы буквально понятия не имеете, что произойдет, если бы вы это сделали, вы бы поймали исключение дальше и обработали его.
источник
Проблема с «исключительными исключениями», то есть исключениями, которые вы не предвидели, заключается в том, что вы не знаете, в каком состоянии находится программа. Например, попытка сохранить данные пользователя может фактически уничтожить еще больше данных .
По этой причине вы должны закрыть приложение.
Есть очень интересная идея под названием Crash- Only Software от Джорджа Кандеа и Армандо Фокса . Идея состоит в том, что если вы разрабатываете свое программное обеспечение таким образом, что единственный способ закрыть его - это его аварийное завершение, а единственный способ запустить его - это восстановление после сбоя, тогда ваше программное обеспечение будет более устойчивым и устранение ошибок. пути кода будут намного более тщательно проверены и реализованы.
Они пришли к этой идее, заметив, что некоторые системы запускаются быстрее после сбоя, чем после упорядоченного выключения.
Хорошим примером, хотя он больше не актуален, являются некоторые старые версии Firefox, которые не только запускаются быстрее при восстановлении после сбоя, но и имеют лучший способ запуска при этом ! В этих версиях, если вы нормально выключите Firefox, он закроет все открытые вкладки и запустит одну пустую вкладку. Принимая во внимание, что при восстановлении после сбоя он восстановит открытые вкладки во время сбоя. (И это был единственный способ закрыть Firefox без потери текущего контекста просмотра.) Итак, что же делали люди? Они просто никогда не закрывали Firefox и вместо этого всегда
pkill -KILL firefox
редактировали его.В блоге Linux Weekly News есть отличная статья о программном обеспечении, предназначенном только для сбоев, Валери Аврора . Комментарии также стоит прочитать. Например, кто-то в комментариях справедливо указывает, что эти идеи не новы и фактически более или менее эквивалентны принципам разработки приложений на основе Erlang / OTP. И, конечно, если взглянуть на это сегодня, еще через 10 лет после Валери и через 15 лет после оригинальной статьи, мы могли бы заметить, что нынешняя ажиотаж в сфере микро-услуг вновь изобретает те же идеи. Современный облачный дизайн центров обработки данных также является примером более грубой детализации. (Любой компьютер может выйти из строя в любое время, не влияя на систему.)
Однако этого недостаточно, чтобы просто позволить вашему программному обеспечению рухнуть. Это должно быть разработано для этого. В идеале ваше программное обеспечение должно быть разбито на небольшие независимые компоненты, каждый из которых может зависать независимо. Кроме того, «механизм сбоя» должен находиться за пределами компонента, в котором происходит сбой.
источник
Правильный способ обработки большинства исключений должен состоять в том, чтобы сделать недействительным любой объект, который в результате может быть поврежден, и продолжить выполнение, если недействительные объекты не предотвращают это. Например, безопасная парадигма для обновления ресурса:
Если при обновлении защищенного ресурса возникает непредвиденное исключение, ресурс должен считаться поврежденным, а блокировка недействительной, независимо от того, относится ли исключение к типу, который в противном случае был бы доброкачественным.
К сожалению, средства защиты ресурсов, реализованные через
IDisposable
/,using
будут освобождаться всякий раз, когда защищаемый блок выходит, без какого-либо способа узнать, вышел ли блок нормально или ненормально. Таким образом, несмотря на то, что должны быть четко определенные критерии того, когда продолжать работу после исключения, невозможно определить, когда они применяются.источник
Вы можете использовать подход, который следует каждому приложению для iOS и MacOS: необработанное исключение немедленно удаляет приложение. Плюс многие ошибки, такие как выход за пределы массива или просто арифметическое переполнение в новых приложениях, делают то же самое. Нет предупреждения
По моему опыту, многие пользователи не обращают на это никакого внимания, а просто снова нажимают на значок приложения.
Очевидно, что вам нужно убедиться, что такой сбой не приведет к значительной потере данных и определенно не приведет к дорогостоящим ошибкам. Но предупреждение «Ваше приложение будет зависать сейчас. Позвоните в службу поддержки, если это вас беспокоит »никому не помогает.
источник