2009-08-19 13 views
6

Esto se relaciona con un previous question.¿Por qué las excepciones de AppDomain invariablemente terminan la aplicación?

Lo que estoy tratando de entender ahora es cómo se puede evitar que las excepciones de subprocesos de UI terminen la aplicación, mientras que las excepciones que no son de UI no se pueden.

Para referencia, vea this example.

Lo que es más importante, lo que me gustaría poder hacer en ese caso es terminar "silenciosamente" el proceso, sin mostrar el cuadro de diálogo de Windows que pregunta si me gustaría enviar un informe de error o no.

Esta es mi dominio de aplicación UnhandledExceptionHandler:

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{    
    try 
    { 
     // Maybe do some logging here if allowed 
    } 
    catch 
    { 
    } 

    // then just terminate the application 
    Application.Exit();    
} 

ACTUALIZACIÓN
A la luz de los comentarios en this answer, me gustaría dejar claro que lo más importante que me gustaría obtener más información sobre el mecanismo que permite que el subproceso de interfaz de usuario tenga una oportunidad temprana de detectar excepciones no controladas a través del mecanismo Application.ThreadException. Y si tal comportamiento podría implementarse en un hilo que no sea UI.

Respuesta

7

Así que, después de hacer algunas más búsquedas en Google Me pareció muy interesante la explicación que se dio al mismo problema que el descrito por Jeff Atwood on his blog.

Hola a todos, Lo siento por la confusión. Este comportamiento es realmente el diseño, aunque el diseño puede ser un poco intrincado a veces.

Lo primero que debe entenderse es que el evento UnhandledException no es un "controlador" de excepción no controlada. Registrarse para el evento, contrariamente a lo que dice la documentación :-(, no hace que se manejen las excepciones no controladas. (Desde entonces no serían no controladas, pero ya voy a dejar el razonamiento circular ...) El evento UnhandledException simplemente le notifica que una excepción se ha ido no controlada, en caso de que desee para tratar de salvar el estado antes de que el hilo o la aplicación muere. Fwiw, he presentado un error para obtener los documentos fijos.

Sólo para complicar las cosas, en v1.0 y 1.1, una excepción no controlada no siempre significaba que su aplicación moriría. Si la excepción no controlada se produjo en algo que no sea el hilo principal o un hilo que comenzó su vida en un código no administrado, el CLR comió la excepción y permitió que su aplicación siguiera funcionando. En general, esto fue malo, porque lo que sucedería a menudo sería, por ejemplo, que los hilos de ThreadPool murieran silenciosamente, uno por uno, hasta que tu aplicación no estuviera realmente haciendo ningún trabajo. Descubrir la causa de este tipo de falla fue casi imposible. Esta puede ser la razón por la cual Jeff pensó que funcionó antes ... él siempre vio bloqueos en hilos no principales.

En v2.0, una excepción no controlada en cualquier subproceso eliminará la aplicación. Descubrimos que es tremendamente más fácil depurar fallas que depurar bloqueos o el problema de detención silenciosa del trabajo descrito anteriormente.

BTW, en mi máquina 1.1 el ejemplo de MSDN tiene la salida esperada; es solo que la segunda línea no aparece hasta después de haber adjuntado un depurador (o no). En v2 hemos cambiado las cosas para que el evento UnhandledException se active antes de que se adjunte el depurador, que parece ser lo que la mayoría de la gente espera.

Jonathan Keljo excepciones CLR PM Jonathan Keljo el 18 de febrero, 2005 22:02

Sin embargo, todavía estoy interesado en cómo el hilo de interfaz de usuario lleva a cabo el truco de permitirle tener un retén -todo controlador para todas las excepciones de subprocesos de UI.

Aún más, estoy muy interesado en una manera de desactivar la depuración de diálogo .NET JIT para mi aplicación sólo (sin disabling it for the whole machine as seen here)

3

No es que ninguna excepción de AppDomain termine la aplicación, es que las excepciones no controladas (de cualquier tipo) derribarán el AppDomain y terminarán la aplicación.

El problema aquí es que puede manejar excepciones de hilos de UI explícitamente, en un nivel bastante alto. Sin embargo, cuando tiene una excepción no controlada en una cadena de fondo, no hay forma de manejarla fácilmente en el mismo nivel, por lo que tiende a propagarse hacia arriba y hacia abajo la aplicación. Application.ThreadException le permite al menos saber que esto es lo que causó el error, y registrarlo si es necesario.

Las excepciones no controladas en el hilo de la interfaz de usuario provocarán que ocurra lo mismo.

+0

@Reed: "Las excepciones no controladas en el hilo de interfaz de usuario hará que la misma cosa que sucederá ". - esto no es verdad. Por favor crea una aplicación de prueba y pruébalo por ti mismo. –

+1

Técnicamente, debería haber dicho "excepciones no controladas en el hilo principal". Windows Forms agrega su propio comportamiento de manejo de excepciones en el hilo de la interfaz de usuario (ya que se ejecuta completamente en el hilo de la interfaz de usuario) que cambia el comportamiento del hilo principal. Cree una aplicación de consola e intente esto, y verá que no importa en qué subproceso ocurran las cosas: todos eliminarán la aplicación. –

+0

Entonces debería replantear mi pregunta: ¿Cómo cumple el hilo de la interfaz de usuario su comportamiento de manejo de excepciones generales? ¿Es eso algo que podría replicar como comportamiento para un hilo que no sea UI? –

2

¿Esto ayuda en absoluto?

Improved Unhandled Exception behavior in .NET 2.0

Además, este código parece a "morir en silencio". Esta buscando algo mas?

using System; 

namespace UnhandledException 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; 

      throw new NotImplementedException(); 
     } 

     static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) 
     { 
      Exception exception = (Exception)e.ExceptionObject; 
      System.Console.WriteLine("exception=[" + exception.ToString() + "]"); 

      Environment.Exit(-1); 
     } 
    } 
} 
+0

Sí, sí. Acabo de leer la publicación y los comentarios cuando publicaste eso. +1 sin embargo ... –

+0

Sí, ¡Environemnt.Exit parece ser el truco! Voy a dejar las preguntas abiertas por un tiempo más para ver si alguien puede dar una idea de cómo el subproceso de la interfaz de usuario logra la excepción catch-all. ¡De lo contrario, tendrás mi voto para la respuesta aceptada! –

+0

Application.ThreadException es solo otra variante de un "manejador de excepciones no controlado". Hay muchas variantes (Aplicación de consola vs. WinForms vs. WebForms vs. WCF, etc.). No estoy seguro de entender tu pregunta. En general, implemento cada uno que sea aplicable. –

Cuestiones relacionadas