visual ventana una terminar salir programa para form example ejecucion como comando cerrar boton aplicacion c# .net multithreading appdomain

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 : se System.AppDomain.CurrentDomain.ProcessExit cuando el proceso finaliza, 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 lugar. Para Windows Forms, ejecute el código después de Application.Run(...) en el método principal.

  • System.AppDomain.CurrentDomain.DomainUnload : se System.AppDomain.CurrentDomain.DomainUnload cuando se descarga un AppDomain que no es AppDomain predeterminado, por ejemplo, al ejecutar clases con marcos de prueba de unidades (MbUnit con TestDriven.NET).

  • System.AppDomain.CurrentDomain.UnhandledException : (si se maneja en AppDomain 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 : se System.Windows.Application.Exit cuando la aplicación WPF (es decir, el AppDomain predeterminado) sale con elegancia. Sustituya System.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

  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 ejecutándose dentro de TestDriven.NET: pasó la prueba (salida elegante)

  1. System.AppDomain.CurrentDomain.DomainUnload
  2. Finalizadores

MbUnit corriendo dentro de TestDriven.NET: prueba fallida (las excepciones no manejadas son manejadas por MbUnit)

  1. AppDomain.CurrentDomain.DomainUnload
  2. 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.?

  1. 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).