2011-05-24 10 views
11

Primero algunos antecedentes: Tengo una aplicación WinForms multiproceso que hace interoperabilidad con dlls nativos. Esta aplicación se cuelga a veces con excepción no controlada y estamos tratando de investigar por qué sucede. Para facilitarlo, estoy creando un controlador global de excepciones y planeo generar un archivo de volcado del proceso a partir de él.Application.ThreadException vs AppDomain.UnhandledException

Ahora viene la pregunta: a partir de ahora esta aplicación tiene controlador para Application.ThreadException pero todavía se bloquea con una excepción no controlada. Estoy pensando en agregar un controlador para AppDomain.UnhandledException también, aunque no estoy seguro si va a ayudar. ¿Existe alguna excepción no controlada posible en este escenario que no sea detectada por Application.ThreadException?

+0

posible duplicado de [¿Cuál es la diferencia entre Application.ThreadException y AppDomain.CurrentDomain.UnhandledException?] (Http://stackoverflow.com/questions/2014562/whats-the-difference-between-application-threadexception-and-appdomain -currentd) – nawfal

Respuesta

20

Sí, Application.ThreadException solo puede interceptar excepciones que se generan en el hilo de la interfaz de usuario. En el código que se ejecuta debido a las notificaciones de Windows. O en términos técnicos, los eventos que se desencadenan por el ciclo del mensaje. La mayoría de los eventos de Winforms se ajustan a esta categoría.

Lo que hace no trampa son excepciones planteadas sobre cualquier tema no interfaz de usuario, como un subproceso de trabajo comenzó con el método de un delegado BeginInvoke() hilo.start(), o ThreadPool.QueueUserWorkItem. Cualquier excepción no controlada en esos terminará la aplicación, AppDomain.UnhandledException es el último grito de asombro.

Yendo más abajo colina abajo, las excepciones de hardware que se generan en un subproceso no administrado por código nativo que nunca realizó ninguna llamada CLR administrada no se pueden detectar con ningún mecanismo CLR. Un AccessViolation (código de excepción 0xc0000005) es la causa más común de muerte. La única forma de atraparlos es a través de la API de Windows, SetUnhandledExceptionFilter(). Esto es difícil de hacer bien.

Puede deshabilitar Application.ThreadException con Application.SetUnhandledExceptionMode(). Lo cual es una buena decisión, darle al usuario la opción Continuar no tiene mucho sentido. Ahora todas las excepciones en subprocesos administrados se comportan igual, use AppDomain.UnhandledException para registrarlas.

7

Application.ThreadException solo será elevada para las excepciones no controladas en las roscas WinForms de interfaz de usuario (véase here.) Adición de un controlador para AppDomain.UnhandledException podría ayudar en este caso (aunque con algunas advertencias, como se describe en la sección de observaciones here.)

3

Le recomiendo que use la generación de minivolcados del sistema operativo en lugar de la suya. Esto es por varias razones:

  1. Generar un minivolcado dentro del mismo proceso es extremadamente problemático y no siempre es posible.
  2. En el momento en que se inicia ThreadException o UnhandledException, la pila de excepciones ya se ha desenrollado. Generar un minivolcado en ese punto solo lo dirigirá al controlador, no a la fuente de la excepción.

Si su aplicación está en el campo, use WER. Si está haciendo pruebas internas, use ProcDump. También puede copiar el archivo de minivolcado mientras el cuadro de diálogo Informes de error está activo.

P.S. Hay algunas condiciones excepcionales, especialmente cuando se realiza p/Invoke, donde ni ThreadException ni UnhandledException funcionarán.

P.P.S. Si tiene un escenario depurable, intente encender el Managed Debugging Assistants relacionado con p/Invoke.

+0

Sí, estoy generando minivolcados OS aunque prefiero usar AdPlus para generar estos volcados. Gracias por el consejo aunque :) –

+0

Aclaro: no es una buena idea tener su código (en el mismo proceso) crear la minidump. Citando la documentación 'MiniDumpWriteDump':' MiniDumpWriteDump debe ser llamado desde un proceso separado, si es posible, en lugar de hacerlo desde el proceso de destino objeto de dumping. Esto es especialmente cierto cuando el proceso objetivo ya no es estable. Por ejemplo, si sólo crashed.' ... 'MiniDumpWriteDump puede no producir un seguimiento de pila válida para la llamada thread.' –

+0

Tener WER o' ProcDump' crear las minivolcados * * para que le evita esos problemas. –

Cuestiones relacionadas