¿Cuál es la diferencia entre Application.ThreadException y AppDomain.CurrentDomain.UnhandledException?

107

Muy bien, este es uno fácil:

  • ¿Cuál es la diferencia entre Application.ThreadExceptiony
    AppDomain.CurrentDomain.UnhandledException?

  • ¿Necesito manejar ambos?

¡Gracias!

JohnIdol
fuente

Respuestas:

98

Application.ThreadException es específico de Windows Forms. Winforms ejecuta controladores de eventos en respuesta a los mensajes que le envía Windows. El evento Click, por ejemplo, estoy seguro de que los conoce. Si tal controlador de eventos arroja una excepción, entonces hay una parada de retorno dentro del bucle de mensajes de Winforms que detecta esa excepción.

Ese respaldo activa el evento Application.ThreadException . Si no lo anula, el usuario obtendrá un ThreadExceptionDialog . Lo que le permite ignorar la excepción y seguir ejecutando su programa. No es una gran idea por cierto.

Puede deshabilitar este comportamiento llamando a Application.SetUnhandledExceptionMode () en el método Main () en Program.cs. Sin ese respaldo en su lugar, sucede lo habitual cuando un hilo muere debido a una excepción no controlada: AppDomain.UnhandledException se activa y el programa termina.

Fwiw: "ThreadException" fue una elección de nombre muy pobre. No tiene nada que ver con hilos.

Hans Passant
fuente
Y cómo evitar que la aplicación WinForms se bloquee cuando se produzca Application.ThreadException. Hice una pregunta para esto [aquí ] con mi pequeño código C #.
Mahesha999
2
Siempre lo leo como una excepción de subproceso de aplicación, dado que winforms está vinculado a un solo subproceso.
Gusdor
36

De la fuente :

En las aplicaciones que usan Windows Forms, las excepciones no controladas en el subproceso de la aplicación principal hacen que se genere el Application.ThreadException evento. Si se controla este evento, el comportamiento predeterminado es que la excepción no controlada no finaliza la aplicación, aunque la aplicación se deja en un estado desconocido. En ese caso, el UnhandledException evento no se genera. Este comportamiento se puede cambiar utilizando el archivo de configuración de la aplicación o utilizando el Application.SetUnhandledExceptionModemétodo para cambiar el modo UnhandledExceptionMode.ThrowExceptionantes de ThreadException que se conecte el controlador de eventos. Esto se aplica solo al hilo de la aplicación principal. El UnhandledException evento se genera para las excepciones no controladas lanzadas en otros subprocesos.

A partir de Visual Studio 2005 , el Visual Basic marco de aplicación proporciona otro evento de excepciones no controladas en el hilo principal de la aplicación - WindowsFormsApplicationBase.UnhandledException. Este evento tiene un objeto de argumentos de evento con el mismo nombre que el objeto de argumentos de evento utilizado por AppDomain.UnhandledException, pero con propiedades diferentes. En particular, este objeto de argumentos de evento tiene una ExitApplicationpropiedad que permite que la aplicación continúe ejecutándose, ignorando la excepción no controlada (y dejando la aplicación en un estado desconocido). En ese caso, no se genera el evento AppDomain.UnhandledException.

Application.ThreadExceptionpuede ser capturado y la aplicación podría continuar (en general no es una gran idea, pero para la aplicación, como ejecutar periódicamente algunas acciones, esta es una buena solución).

Para detectar las excepciones que se producen en subprocesos que no son creados ni propiedad de Windows Forms, utilice la extensión AppDomain.UnhandledException. Permite que la aplicación registre información sobre la excepción antes de que el controlador predeterminado del sistema informe la excepción al usuario y finalice la aplicación.
El manejo de esta excepción no impide que se termine la aplicación.
Lo máximo que se puede hacer (los datos del programa pueden dañarse si no se manejan las excepciones) es guardar los datos del programa para su posterior recuperación. Después de eso, el dominio de la aplicación se descarga y la aplicación termina.

A partir de .NET 4 , este evento no se genera para excepciones que corrompen el estado del proceso, como desbordamientos de pila o violaciones de acceso, a menos que el controlador de eventos sea crítico para la seguridad y tenga el HandleProcessCorruptedStateExceptionsAttribute atributo.

Para obtener más detalles, consulte MSDN .

serhio
fuente
18

De acuerdo, lo tenía frente a mí, este fragmento de código de msdn se explica por sí mismo:

public static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new 
        ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

    // Set the unhandled exception mode to force all Windows Forms 
    // errors to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    // Runs the application.
    Application.Run(new ErrorHandlerForm());
}
JohnIdol
fuente
3
esto contrasta con la otra respuesta de serhio cuando dice: UnhandledExceptionMode.ThrowException debe establecerse antes de que se conecte el controlador de eventos ThreadException. No estoy seguro si el orden realmente importa ...
Davide Piras
@DavidePiras sí, y hay algo más turbio. SetUnhandledException parece no hacer ninguna diferencia en mi caso.
nawfal
0

Bueno, la cosa es que ThreadExceptionocurre debido a un problema con su hilo, el Unhandled Exceptionse dispara si su código lanza una excepción que no se maneja.

Una forma más fácil de provocar el segundo es crear una aplicación sin intentarlo ... atrapar bloques y lanzar una excepción.

Ahora bien, si necesita un seguro, puede manejar ambos, sin embargo, si captura y maneja exceptionscorrectamente, entonces no debería necesitar al UnhandledExceptioncontrolador, ya que es una especie de trampa para todos.

Joshua Cauble
fuente
gracias, lo que no tenía muy claro era si al manejar UnhandledException también atraparía ThreadException, que parece no ser el caso
JohnIdol