2009-09-03 10 views
61

Este es un seguimiento de mi initial question y me gustaría presentar mis hallazgos y solicitar correcciones, ideas y perspectivas. Mis hallazgos (o más bien interpretaciones) provienen de las respuestas de las personas a mi pregunta anterior, leyendo la documentación de MSDN .NET 3.5 y depurando el código de .NET 3.5. Espero que esto sea valioso para alguien que se preguntaba cómo detectar cuándo finaliza una aplicación.¿Cómo detectar cuando finaliza la aplicación?

Eventos:

  • System.AppDomain.CurrentDomain.ProcessExit: planteadas cuando las salidas de proceso, por ejemplo, después del AppDomain predeterminado y todo lo demás se descargó [El tiempo de ejecución total está limitado a solo 3 segundos!]. Para WPF, use System.Windows.Application.Exit en su lugar. Para Windows Forms, ejecute el código después de Application.Run(...) en el método principal.

  • System.AppDomain.CurrentDomain.DomainUnload: plantearon cuando un AppDomain distinto predeterminado AppDomain se descargue, por ejemplo cuando se ejecutan clases con marcos de prueba de unidades (MbUnit con TestDriven.NET).

  • System.AppDomain.CurrentDomain.UnhandledException: (si se maneja en su defecto AppDomain :) levantó para cualquier excepción no controlada en cualquier tema, no importa lo AppDomain el hilo se inició en este medio, esto puede ser usado como el cajón de sastre para todas las excepciones no controladas..

  • System.Windows.Application.Exit: se genera cuando la aplicación WPF (es decir, el valor predeterminado AppDomain) sale correctamente. Anule System.Windows.Application.OnExit para aprovecharlo.

  • Finalizadores (destructores en C#): se ejecuta cuando el recolector de basura libera recursos no administrados. [El tiempo total de ejecución es limitado!].

orden de los acontecimientos:

aplicación de WPF: salida elegante

  1. System.Windows.Application.Exit
  2. System.AppDomain.CurrentDomain.ProcessExit
  3. finalizadores

aplicación WPF: excepción no controlada

  1. System.AppDomain.CurrentDomain.UnhandledException

MbUnit ejecuta dentro TestDriven.NET: prueba superada (salida elegante)

  1. System.AppDomain.CurrentDomain.DomainUnload
  2. finalizadores

MbUnit ejecutándose dentro de TestDriven.NET: fallado la prueba (las excepciones no controladas son manejados por MbUnit)

  1. AppDomain.CurrentDomain.DomainUnload
  2. finalizadores

Preguntas:

  • son mis interpretaciones/hallazgos correcta?
  • ¿Usted sabe de más detalles que tengo dejado afuera? P.ej. ¿Cuál es el tiempo total de ejecución para los finalizadores?
  • ¿Conoces otros eventos/ ideas que tenga en cuenta?
  • Qué eventos hay y qué orden se obtienen en otras aplicaciones, p. Formularios de Windows, servicio web, sitio web ASP.NET, etc.

Respuesta

7

Impulsada por ssg31415926 de pregunta/respuesta (esta pregunta es un poco al revés), también hay Application.SessionEnding que se llama cuando el cuando el usuario cierra la sesión o se apaga. Se llama antes del evento de Salida.

+0

Sólo una nota/FYI: esto sólo está disponible en 3.0 + NET, deberá vincular contra System.Core.dll utilizar en .NET 2.0 –

1
  1. El tiempo de espera predeterminado para la ejecución de un finalizador es de 2 segundos.
+0

Tienes una fuente para eso, ¿verdad? – mbx

+1

@mbx http://msdn.microsoft.com/en-us/library/system.appdomain.processexit.aspx –

2

Cuando se llama Dispatcher.BeginInvokeShutdown(), Application.Exit no se llamará.

1

escribe:

System.AppDomain.CurrentDomain.UnhandledException:. (Si se maneja en el dominio de aplicación por defecto :) planteado para cualquier excepción no controlada en cualquier tema, no importa lo que el hilo dominio de aplicación se inició en este medio, esto se puede usar como el todo para todas las excepciones no controladas.

No creo que esto sea correcto. Pruebe el siguiente código:

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); 
      } 
     } 
    } 
} 

Por lo que yo puedo decir, el manejador de UnhandledException Nunca se llama, y ​​el hilo se acaba de chocar en silencio (o darle la lata a que si se ejecuta en el depurador).

+0

Encontré esa línea poco clara, también. Tal vez @ user65199 significaba si el * evento * se "manejaba en el AppDomain predeterminado". Obviamente, si se captura la excepción, el evento UnhandledException no se genera. ¿El evento solo se plantea en el AppDomain predeterminado, incluso para excepciones no controladas en hilos realmente iniciados en otro AppDomain (a diferencia de tu ejemplo a partir del AppDomain predeterminado)? Creo que puede ser a lo que estaba llegando, pero no recuerdo con certeza si esa es la regla. –

0

Sólo tiene que añadir un nuevo evento en su forma principal:

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