Сохранять приложение, даже если выполняется необработанное исключение
Что?
Я разрабатываю консольное приложение, которое должно работать 24/7 No Matter What
Существует ли способ остановить многопоточное приложение от взорванного каким-то необработанным исключением, происходящим в "некоторых нить где-нибудь"?
Почему?
Пожалуйста, воздержитесь от уроков, таких как "вы должны управлять всеми своими исключениями", "этого никогда не должно быть" и т.д. У меня есть свои причины: мы находимся в тестовом развертывании, и нам нужно сохранить это выполнение, исключить журналы и снова перезапустить все потоки. Если происходит что-либо незапланированное, и возникает необработанное исключение, оно должно быть обнаружено, и какой-либо метод вызывается для перезапуска всех потоков (атомарность невозможна из-за конструкции уровня)
При этом я знаю, что было бы невозможно перезапустить приложение из "внутри", если оно произошло из-за и UnhandledException (которое я уже реализовал).
До сих пор я использовал Quartz.net FileScan Job и Flag File для обнаружения таких вещей и перезапуска приложения извне. Но это звучит для меня неловко. Я хотел бы найти что-то более чистое и менее быстрое и грязное.
DownVoting/Sniping Warning: Я ЗНАЮ, что это НЕ МОЖЕТ быть "как есть".
Пожалуйста, будьте креативными/полезными, а не критически критикуйте и подумайте об этом как о "Открытом вопросе"
Ответы
Ответ 1
Вам необходимо привязать обработчик события к событию UnhandledException в Current AppDomain:
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler
Внутри обработчика вам нужно как-то сэкономить достаточное состояние (для файла, базы данных и т.д.) для перезапуска приложения, чтобы перейти к новым потокам. Затем создайте экземпляр нового экземпляра вашего консольного приложения с вызовом System.Diagnostics.Process.Start("MyConsoleApp.exe")
.
Будьте очень осторожны, чтобы ввести логику, чтобы избежать непрерывного цикла сбоя/перезагрузки/сбоя/перезагрузки.
Ответ 2
Если все равно будет работать 24/7, почему бы не просто записать его как службу Windows и воспользоваться преимуществами встроенных функций восстановления прямо в окна?
![Configuring Recovery Services]()
Этот подход имеет дополнительное преимущество, заключающееся в том, что он может пережить перезагрузку компьютера, и он будет регистрировать сбои/перезапуска в журналах системных событий.
Ответ 3
- не может поддерживать процесс "независимо от того, что". Что делать, если процесс убит?
- Вы не хотите, чтобы продолжал работать, несмотря ни на что. Что делать, если состояние процесса повреждено таким образом, что "плохие вещи" происходят, если он продолжает работать?
Ответ 4
Ну, я могу придумать несколько недостатков в следующем решении, но для меня это достаточно хорошо:
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
CS = new ConsoleServer();
CS.Run();
}
public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exception = (Exception)e.ExceptionObject;
Logger.Log("UNHANDLED EXCEPTION : " + e.ExceptionObject.ToString());
Process.Start(@"C:\xxxx\bin\x86\Release\MySelf.exe");
}
Ответ 5
Если вы используете .Net 2.0 и выше, ответ вы не можете.
В .NET Framework версии 1.0 и 1.1 необработанное исключение которое происходит в потоке, отличном от основного потока приложения, пойманы во время выполнения и, следовательно, не приводят к тому, что приложение прекратить. Таким образом, событие UnhandledException может быть поднятый без завершения заявки. Начиная с .NET. Рамочная версия 2.0, эта блокировка для необработанных исключений в дочернем нити были удалены, потому что кумулятивный эффект такого молчания ошибки включали снижение производительности, поврежденные данные и блокировки, все из которых были трудно отлаживать. Чтобы получить больше информации, включая список случаев, когда время выполнения не завершается, см. Исключения в управляемых потоках.
Взято отсюда:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Если вы хотите, чтобы ваше приложение выжило, вам понадобится очень агрессивная попытка/улов вокруг ваших методов, чтобы ничего не ускользнуло.
Я бы посоветовал использовать службу Windows, как упоминалось другими. Это то же самое, что и консольное приложение, но с дополнительным битом кода уровня обслуживания сверху. Вы можете использовать консольное приложение и легко скрывать его в сервисном приложении. Просто нужно переопределить методы service.start/pause/stop.