Ответ 1
Подскажите по ssg31415926 вопрос/ответ (этот вопрос немного изменился), там также Application.SessionEnding, который вызывается, когда пользователь выходит из системы или выключается. Он вызывается перед событием Exit.
Это продолжение моего начального вопроса, и я хотел бы представить свои выводы и запросить исправления, идеи и идеи. Мои выводы (или, скорее, интерпретации) исходят от ответов людей на мой предыдущий вопрос, читая документацию MSDN.NET 3.5 и отлаживая код .NET 3.5. Надеюсь, это будет полезно для тех, кто задавался вопросом, как я обнаруживаю, когда приложение прекращается.
События:
System.AppDomain.CurrentDomain.ProcessExit
: повышается, когда процесс завершается, например. после по умолчанию AppDomain
и все остальное было выгружено [Общее время выполнения ограничено всего 3 секунды!]. Для WPF используйте System.Windows.Application.Exit
вместо этого. Для Windows Forms запустите код после Application.Run(...)
в основном методе.
System.AppDomain.CurrentDomain.DomainUnload
: поднят, когда AppDomain
отличается от по умолчанию AppDomain
выгружает, например. при запуске классов с модульными модулями тестирования (MbUnit с TestDriven.NET).
System.AppDomain.CurrentDomain.UnhandledException
: (если обрабатывается по умолчанию AppDomain
:), поднятый для любого необработанного исключения в любом потоке, независимо от того, какой AppDomain
был запущен поток. Это означает, что это можно использовать как catch -все для всех необработанных исключений.
System.Windows.Application.Exit
: поднят, когда приложение WPF (т.е. по умолчанию AppDomain
) выходит изящно. Переопределите System.Windows.Application.OnExit
, чтобы воспользоваться им.
Финализаторы (деструкторы в С#): запускаются, когда сборщик мусора освобождает неуправляемые ресурсы. [Общее время выполнения ограничено!].
Порядок событий:
Приложение WPF: изящный выход
System.Windows.Application.Exit
System.AppDomain.CurrentDomain.ProcessExit
Приложение WPF: необработанное исключение
System.AppDomain.CurrentDomain.UnhandledException
MbUnit работает внутри TestDriven.NET: прошел тест (изящный выход)
System.AppDomain.CurrentDomain.DomainUnload
MbUnit работает внутри TestDriven.NET: сбой теста (необработанные исключения обрабатываются MbUnit)
AppDomain.CurrentDomain.DomainUnload
Вопросы:
Подскажите по ssg31415926 вопрос/ответ (этот вопрос немного изменился), там также Application.SessionEnding, который вызывается, когда пользователь выходит из системы или выключается. Он вызывается перед событием Exit.
Когда вызывается Dispatcher.BeginInvokeShutdown()
, Application.Exit
не будет вызываться.
Вы пишете:
System.AppDomain.CurrentDomain.UnhandledException: (если обрабатывается по умолчанию AppDomain:), поднятый для любого необработанного исключения в любом потоке, независимо от того, в какой среде AppDomain запущен поток. Это означает, что это можно использовать как средство для всех все необработанные исключения.
Я не думаю, что это правильно. Попробуйте следующий код:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AppDomainTestingUnhandledException
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
(sender, eventArgs) => Console.WriteLine("Something went wrong! " + args);
var ad = AppDomain.CreateDomain("Test");
var service =
(RunInAnotherDomain)
ad.CreateInstanceAndUnwrap(
typeof(RunInAnotherDomain).Assembly.FullName, typeof(RunInAnotherDomain).FullName);
try
{
service.Start();
}
catch (Exception e)
{
Console.WriteLine("Crash: " + e.Message);
}
finally
{
AppDomain.Unload(ad);
}
}
}
class RunInAnotherDomain : MarshalByRefObject
{
public void Start()
{
Task.Run(
() =>
{
Thread.Sleep(1000);
Console.WriteLine("Uh oh!");
throw new Exception("Oh no!");
});
while (true)
{
Console.WriteLine("Still running!");
Thread.Sleep(300);
}
}
}
}
Насколько я могу судить, обработчик UnhandledException никогда не вызывается, и поток просто бесшумно рушится (или натыкается на вас, если вы запустите его в отладчике).
Просто добавьте новое событие в свою основную форму:
private void frmMain_Load(object sender, EventArgs e)
{
Application.ApplicationExit += new EventHandler(this.WhenItStopsDoThis);
}
private void WhenItStopsDoThis(object sender, EventArgs e)
{
//Program ended. Do something here.
}