{"id":55896,"date":"2010-08-05T17:39:00","date_gmt":"2010-08-05T17:39:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2010\/08\/05\/faq-taskscheduler-unobservedtaskexception-event-doesnt-work\/"},"modified":"2010-08-05T17:39:00","modified_gmt":"2010-08-05T17:39:00","slug":"faq-taskscheduler-unobservedtaskexception-event-doesnt-work","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/faq-taskscheduler-unobservedtaskexception-event-doesnt-work\/","title":{"rendered":"FAQ :: TaskScheduler.UnobservedTaskException event doesn\u2019t work?"},"content":{"rendered":"<p class=\"MsoNormal\"><span style=\"font-family: Calibri\"><span style=\"color: black;font-size: 12pt\">Recall that if exceptions thrown from Task bodies are left unobserved, they will be escalated.&nbsp; In .NET 4, this means that TPL will throw them on the finalizer after the Task objects are available for garbage collection.&nbsp; 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.&nbsp; Therefore, code like the following will <b>not<\/b> trigger the event:<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Calibri\"><span style=\"color: black;font-size: 12pt\"><br \/><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\">TaskScheduler<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">.UnobservedTaskException +=<br \/>&nbsp;&nbsp;&nbsp; (<\/span><span style=\"font-family: Consolas;color: blue;font-size: 10pt\">object<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> sender, <\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\">UnobservedTaskExceptionEventArgs<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> excArgs) =&gt;<br \/>{<br \/>&nbsp;&nbsp;&nbsp; <\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\">Console<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">.WriteLine(<\/span><span style=\"font-family: Consolas;color: #a31515;font-size: 10pt\">&#8220;Caught it!&#8221;<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">);<br \/>&nbsp;&nbsp;&nbsp; excArgs.SetObserved();<br \/>};<br \/><\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\"><br \/>Task<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> t = <\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\">Task<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">.Factory.StartNew(() =&gt;<br \/>{<br \/><\/span><span style=\"font-family: Consolas;color: blue;font-size: 10pt\">&nbsp;&nbsp;&nbsp; throw<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> <\/span><span style=\"font-family: Consolas;color: blue;font-size: 10pt\">new<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> <\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\">Exception<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">(<\/span><span style=\"font-family: Consolas;color: #a31515;font-size: 10pt\">&#8220;ha!&#8221;<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">);<br \/>});<\/p>\n<p><\/span><span style=\"font-family: Consolas;color: blue;font-size: 10pt\">try<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> { t.Wait(); }<br \/><\/span><span style=\"font-family: Consolas;color: blue;font-size: 10pt\">catch<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\"> (<\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 10pt\">Exception<\/span><span style=\"font-family: Consolas;color: black;font-size: 10pt\">) { }<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Consolas;color: black;font-size: 10pt\"><br \/><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Calibri\"><span style=\"color: black;font-size: 12pt\">This is because the Task exception is already being correctly observed by calling Wait()!&nbsp; There&rsquo;s no reason to trigger the event, because the exception will not be escalated anyway.<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Calibri\"><span style=\"color: black;font-size: 12pt\"><\/span><span style=\"font-family: 'Times New Roman','serif';color: black;font-size: 12pt\"><\/span><\/span>&nbsp;<\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Calibri\"><span style=\"color: black;font-size: 12pt\">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).&nbsp; Thus, one way to see the event in action is to do something like this (replacing the try\/catch block above):<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Calibri\"><span style=\"color: black;font-size: 12pt\"><br \/><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">((<\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 9.5pt\">IAsyncResult<\/span><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">)t).AsyncWaitHandle.WaitOne();<br \/><\/span><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">t = <\/span><span style=\"font-family: Consolas;color: blue;font-size: 9.5pt\">null<\/span><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">;<br \/><\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 9.5pt\">GC<\/span><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">.Collect();<br \/><\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 9.5pt\">GC<\/span><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">.WaitForPendingFinalizers();<br \/><\/span><span style=\"font-family: Consolas;color: #2b91af;font-size: 9.5pt\">GC<\/span><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\">.Collect();<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-family: Consolas;color: black;font-size: 9.5pt\"><br \/><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"color: black;font-size: 12pt\"><span style=\"font-family: Calibri\"><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"color: black;font-size: 12pt\"><span style=\"font-family: Calibri\">First, we wait for the Task to complete using its underlying wait handle; this does not observe exceptions like calling Task.Wait() does.&nbsp; Then, we null the Task, making it available for garbage collection, and force a full collection.&nbsp; See the attached file for the code in entirety.<\/span><\/span><\/p>\n<p><span style=\"color: black;font-size: 12pt\"><span style=\"font-family: Calibri\"><\/p>\n<p class=\"MsoNormal\" style=\"line-height: normal;margin: 0in 0in 10pt\"><b><span style=\"color: black;font-size: 12pt\">NOTE: <\/span><\/b><span style=\"color: black;font-size: 12pt\">This sample is intended to let folks experiment with the UnobservedTaskException event.<span>&nbsp; <\/span>It is certainly not recommended for production code.<\/span><span style=\"font-family: 'Times New Roman','serif';color: black;font-size: 12pt\"><\/span><\/p>\n<p><\/span><\/span><\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/MSDNBlogsFS\/prod.evol.blogs.msdn.com\/CommunityServer.Components.PostAttachments\/00\/10\/04\/68\/19\/UnobservedExceptionEventDemo.cs\">UnobservedExceptionEventDemo.cs<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recall that if exceptions thrown from Task bodies are left unobserved, they will be escalated.&nbsp; In .NET 4, this means that TPL will throw them on the finalizer after the Task objects are available for garbage collection.&nbsp; The UnobservedTaskException event on the TaskScheduler class was added as a last-resort method to observe such exceptions and [&hellip;]<\/p>\n","protected":false},"author":485,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[7907,7911,7923,7912],"class_list":["post-55896","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4","tag-code-samples","tag-faq","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>Recall that if exceptions thrown from Task bodies are left unobserved, they will be escalated.&nbsp; In .NET 4, this means that TPL will throw them on the finalizer after the Task objects are available for garbage collection.&nbsp; The UnobservedTaskException event on the TaskScheduler class was added as a last-resort method to observe such exceptions and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55896","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/485"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=55896"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55896\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=55896"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=55896"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=55896"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}