Сохранять приложение, даже если выполняется необработанное исключение

Что?
Я разрабатываю консольное приложение, которое должно работать 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.