Basado en mi investigación, he aprendido lo siguiente:TaskScheduler.UnobservedTaskException nunca se llama
TaskScheduler.UnobservedTaskException
debe esperar a que la tarea sea recolectado antes excepción no observada de esa tarea que estará circulando hasta el eventoUnobservedTaskException
.- , si nunca usas
Task.Wait()
, nunca se llamará de todos modos, porque estás bloqueando un resultado inminente de la Tarea, por lo tanto, la excepción se lanzará alTask.Wait()
en lugar del eventoUnobservedException
. - Llamar a
GC.Collect()
manualmente es generalmente una mala idea a menos que sepa exactamente lo que está haciendo, por lo tanto, es bueno en este caso para confirmar las cosas, pero no como una solución adecuada al problema.
El problema
Si mi aplicación se cierra antes de que el recolector de basura entra en acción, estoy totalmente de 100% no puede conseguir mi evento UnobservedTaskException
al fuego.
Nota el siguiente código:
class Program
{
static void Main(string[] args)
{
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Task.Factory.StartNew(() =>
{
Console.WriteLine("Task started.");
throw new Exception("Test Exception");
});
Thread.Sleep(1000);
//GC.Collect();
//GC.WaitForPendingFinalizers();
}
static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
File.WriteAllText(@"C:\data\TestException.txt", e.Exception.ToString());
Console.WriteLine("EXCEPTION UNOBSERVED");
}
}
Sin archivo de excepciones está escrito y nada se escribe en la consola. Pueden transcurrir de 10 a 15 minutos y más después de que la aplicación finalice y aún así no veo evidencia de que los restos de mi aplicación hayan sido recolectados. Podrías preguntar, ¿por qué no solo cobrar a la salida? Bueno, mi escenario en el mundo real es que mi captura de excepciones se ejecuta dentro de un servicio WCF alojado dentro de un servicio de Windows. No puedo interceptar cuando el servicio de Windows se está cerrando (y por lo tanto llamar manualmente al GC.Collect()
) porque no hay ningún evento para el que yo pueda ver.
¿Dónde me equivoco? ¿Cómo me aseguro de que si algo profundamente dentro del servicio WCF finalmente va a romper mi servicio de Windows, tengo la oportunidad de registrar la excepción antes de que el servicio se caiga?
Hola, gracias por la sugerencia, aunque en realidad ya la estoy ejecutando fuera del depurador.También noto que estás usando GC.Collect(). ¿Qué sucede en tu ejemplo si no recolectas manualmente? –
@Nathan: Normalmente, no hay suficiente presión de GC para que esto suceda en este simple ejemplo. Si el GC no se recopila, la "tarea" no llegará al finalizador, y la excepción no observada nunca se activará. Solo ocurre cuando el finalizador recopila una tarea no rooteada con una excepción. –
@ Nathan: Tenga en cuenta que UnobservedTaskException no evitará que la aplicación se cierre en ningún caso; necesita manejar sus excepciones dentro de su tarea, o siempre esperar en una tarea, si desea evitar que esto cierre una aplicación. –