Как определить, когда приложение завершается?

Это продолжение моего начального вопроса, и я хотел бы представить свои выводы и запросить исправления, идеи и идеи. Мои выводы (или, скорее, интерпретации) исходят от ответов людей на мой предыдущий вопрос, читая документацию 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
  • Финализаторы

Вопросы:

  • Являются ли мои интерпретации/выводы правильными?
  • Знаете ли вы более подробную информацию о том, что у меня есть опущены? Например. какова общая сумма время выполнения для финализаторов?
  • Знаете ли вы о других событиях/ идеи, о которых я знаю?
  • Какие события существуют и какой порядок они поднимают в других приложениях, например. Windows Forms, веб-сервис, веб-сайт ASP.NET и т.д.

Ответ 1

Подскажите по ssg31415926 вопрос/ответ (этот вопрос немного изменился), там также Application.SessionEnding, который вызывается, когда пользователь выходит из системы или выключается. Он вызывается перед событием Exit.

Ответ 2

Когда вызывается Dispatcher.BeginInvokeShutdown(), Application.Exit не будет вызываться.

Ответ 3

  1. Тайм-аут по умолчанию для выполнения финализатора составляет 2 секунды.

Ответ 4

Вы пишете:

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 никогда не вызывается, и поток просто бесшумно рушится (или натыкается на вас, если вы запустите его в отладчике).

Ответ 5

Просто добавьте новое событие в свою основную форму:

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.
}