c# - ventana - ¿Cómo detectar cuándo termina la aplicación?
como cerrar mi aplicacion en c# (5)
Este es un seguimiento de mi pregunta inicial y me gustaría presentar mis hallazgos y solicitar correcciones, ideas e ideas. 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.
Eventos:
System.AppDomain.CurrentDomain.ProcessExit
: seSystem.AppDomain.CurrentDomain.ProcessExit
cuando el proceso finaliza, por ejemplo, después delAppDomain
predeterminado y todo lo demás se descargó [El tiempo de ejecución total está limitado a solo 3 segundos!]. Para WPF, useSystem.Windows.Application.Exit
lugar. Para Windows Forms, ejecute el código después deApplication.Run(...)
en el método principal.System.AppDomain.CurrentDomain.DomainUnload
: seSystem.AppDomain.CurrentDomain.DomainUnload
cuando se descarga unAppDomain
que no esAppDomain
predeterminado, por ejemplo, al ejecutar clases con marcos de prueba de unidades (MbUnit con TestDriven.NET).System.AppDomain.CurrentDomain.UnhandledException
: (si se maneja enAppDomain
predeterminado) planteado para cualquier excepción no controlada en cualquier hilo, sin importar en quéAppDomain
comenzado el hilo. Esto significa que se puede usar como catch-all para todas las excepciones no controladas .System.Windows.Application.Exit
: seSystem.Windows.Application.Exit
cuando la aplicación WPF (es decir, elAppDomain
predeterminado) sale con elegancia. SustituyaSystem.Windows.Application.OnExit
para aprovecharlo.Finalizadores (destructores en C #): se ejecutan cuando el recolector de basura libera recursos no administrados. [El tiempo total de ejecución es limitado!].
Orden de eventos:
Aplicación WPF: salida elegante
-
System.Windows.Application.Exit
-
System.AppDomain.CurrentDomain.ProcessExit
- Finalizadores
Aplicación WPF: excepción no controlada
-
System.AppDomain.CurrentDomain.UnhandledException
MbUnit ejecutándose dentro de TestDriven.NET: pasó la prueba (salida elegante)
-
System.AppDomain.CurrentDomain.DomainUnload
- Finalizadores
MbUnit corriendo dentro de TestDriven.NET: prueba fallida (las excepciones no manejadas son manejadas por MbUnit)
-
AppDomain.CurrentDomain.DomainUnload
- Finalizadores
Preguntas:
- ¿Son correctas mis interpretaciones / hallazgos?
- ¿Conoces más detalles que he omitido? Por ejemplo, ¿cuál es el tiempo de ejecución total para los finalizadores?
- ¿Conoces algún otro evento / idea del que sea consciente?
- ¿Qué eventos existen y qué orden se plantean en otras aplicaciones, por ejemplo, Windows Forms, Web Service, ASP.NET web site, etc.?
- El tiempo de espera predeterminado para la ejecución de un finalizador es de 2 segundos.
Cuando se llama a Dispatcher.BeginInvokeShutdown()
, no se Application.Exit
.
Impulsado por la pregunta / respuesta de ssg31415926 (esta pregunta está un poco revertida), también hay Application.SessionEnding que se llama cuando el usuario cierra la sesión o se cierra. Se llama antes del evento de Salida.
Solo agrega un nuevo evento en tu formulario 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.
}
Usted escribe:
System.AppDomain.CurrentDomain.UnhandledException: (si se maneja en AppDomain predeterminado) planteado para cualquier excepción no controlada en cualquier hilo, sin importar en qué dominio de aplicación haya comenzado el hilo. Esto significa que se puede usar como catch-all 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 puedo decir, nunca se llama al controlador UnhandledException, y el hilo simplemente se bloqueará silenciosamente (o le molestará si lo ejecuta en el depurador).