Based on my research, I have learned the following:
TaskScheduler.UnobservedTaskException
must wait for the task to be garbage collected before that task's unobserved exception will bubble up to theUnobservedTaskException
event.- If you're using
Task.Wait()
, it'll never get called anyway, because you're blocking on an impending result from the Task, hence the exception will be thrown onTask.Wait()
rather than bubble up to theUnobservedException
event. - Calling
GC.Collect()
manually is generally a bad idea unless you know exactly what you're doing, hence it's good in this case for confirming things, but not as a proper solution to the issue.
The Problem
If my application exits before the garbage collector kicks in, I absolutely 100% cannot get my UnobservedTaskException
event to fire.
Note the following code:
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");
}
}
No exception file is written and nothing is written to the console. 10-15 minutes and more can go by after the application exits and still I see no evidence that my application's remains were garbage collected. You might ask, well why not just collect on exit? Well, my real world scenario is that my exception trapping runs inside a WCF service hosted inside a Windows service. I cannot trap when the Windows service is shutting down (and hence manually call GC.Collect()
) because there is no event for that as far as I can see.
Where am I going wrong? How do I ensure that if something deep inside the WCF service is going to ultimately break my windows service, that I have a chance to log the exception before the service falls over?