FAQ :: TaskScheduler.UnobservedTaskException event doesn’t work?

FAQ :: TaskScheduler.UnobservedTaskException event doesn’t work?

  • Comments 4

Recall that if exceptions thrown from Task bodies are left unobserved, they will be escalated.  In .NET 4, this means that TPL will throw them on the finalizer after the Task objects are available for garbage collection.  The UnobservedTaskException event on the TaskScheduler class was added as a last-resort method to observe such exceptions and prevent them from crashing the process.  Therefore, code like the following will not trigger the event:


TaskScheduler.UnobservedTaskException +=
    (
object sender, UnobservedTaskExceptionEventArgs excArgs) =>
{
   
Console.WriteLine("Caught it!");
    excArgs.SetObserved();
};

Task
t = Task.Factory.StartNew(() =>
{
    throw new Exception("ha!");
});

try { t.Wait(); }
catch (Exception) { }


This is because the Task exception is already being correctly observed by calling Wait()!  There’s no reason to trigger the event, because the exception will not be escalated anyway.

 

Note that even if the Wait() call is removed from the code, the event will not trigger until the Task is available for garbage collection (and a collection actually happens).  Thus, one way to see the event in action is to do something like this (replacing the try/catch block above):


((IAsyncResult)t).AsyncWaitHandle.WaitOne();
t = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();


First, we wait for the Task to complete using its underlying wait handle; this does not observe exceptions like calling Task.Wait() does.  Then, we null the Task, making it available for garbage collection, and force a full collection.  See the attached file for the code in entirety.

NOTE: This sample is intended to let folks experiment with the UnobservedTaskException event.  It is certainly not recommended for production code.

Attachment: UnobservedExceptionEventDemo.cs
Leave a Comment
  • Please add 2 and 3 and type the answer here:
  • Post
  • I _really_ would remove the last piece of code because it will be taken as sample code by people not understanding the full picture...

  • A legitimate concern - thanks tobi.  I think the last bit of code is still valuable, as it clearly shows what the the event is doing (better than prose can).  For now, I've just added a note clarifying the intent of the sample.  I hope folks will heed it =).

  • You dont call  arbitrary code  in the finalizer thread, dont you?

  • UnobservedTaskException is an event, so you can hook up event handlers to it to run whatever code you want.  However, UnobservedTaskException is also [SecurityCritical], which means you need to be trusted to add such code.

Page 1 of 1 (4 items)