{"id":6,"date":"2015-08-10T19:12:00","date_gmt":"2015-08-10T19:12:00","guid":{"rendered":""},"modified":"2016-01-30T22:25:31","modified_gmt":"2016-01-30T22:25:31","slug":"tpl-exception-handling-and-unobservedtaskexception-issue","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2015\/08\/10\/tpl-exception-handling-and-unobservedtaskexception-issue\/","title":{"rendered":"TPL &#8211; exception handling and UnobservedTaskException issue"},"content":{"rendered":"<h3>1. Introduction<\/h3>\n<p>Working with <i>Tasks<\/i> is a modern way of writing asynchronous code in an easy and flexible manner. It is quite straightforward to start using them, so usually developers do not investigate thoroughly the topic. Unfortunately this often leads to unpleasant surprises &#8211; especially when it comes to exception handling. Having this in mind let&#8217;s take a look how to handle exceptions in <i>Task<\/i> and what can happen if we do it wrong.<\/p>\n<h3>2. Exception handling<\/h3>\n<p>Because of the fact that <i>Tasks<\/i> are run asynchronously we can&#8217;t just use a standard <i>try catch<\/i> block surrounding <i>Task<\/i><\/p>\n<pre>\r\npublic static void TryCatchBlockWrongWay()\r\n{\r\n    try\r\n    {\r\n        Task.Factory.StartNew(() => { throw new Exception(\"From method TryCatchBlockWrongWay\"); });\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        \/\/ this will never be hit\r\n        Console.WriteLine(\"Exception handled {0}\", ex);\r\n    }\r\n}\r\n<\/pre>\n<p>In that case catch block is unreachable (I will describe later what happens with that exception), of course we could use <i>try catch<\/i> inside <i>Task.Factory.StartNew<\/i> lambda expression but this is not always the case. Usually we want to handle exception in the caller of the <i>Task<\/i>, not inside the <i>Task<\/i> itself. There are couple of ways of achieving that &#8211; depending on the situation you can use one of the following ways. Exception are propagated to caller once you start waiting for the result of <i>Task<\/i>. So basically you can use <i>try catch<\/i> block if you wait for a <i>Task<\/i> to finish &#8211; either by accessing <i>Result<\/i> property or using <i>Wait<\/i> method<\/p>\n<pre>\r\npublic static void HandleExceptionTryCatchResult()\r\n{\r\n    try\r\n    {\r\n        var task = Task.Factory.StartNew(() =>\r\n        {\r\n            throw new Exception(\"From method HandleExceptionTryCatchResult\");\r\n            return 1;\r\n        });\r\n        \/\/ do more stuff while task is running\r\n        \/\/ do more stuff while task is running\r\n        \/\/ do more stuff while task is running\r\n        var result = task.Result;\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        Console.WriteLine(\"HandleExceptionTryCatchResult: exception handled in try catch block. Exception is {0}\", ex);\r\n    }\r\n}\r\n\r\npublic static void HandleExceptionTryCatchWait()\r\n{\r\n    try\r\n    {\r\n        var task = Task.Factory.StartNew(() => { throw new Exception(\"From method HandleExceptionTryCatchWait\"); });\r\n        \/\/ do more stuff while task is running\r\n        \/\/ do more stuff while task is running\r\n        \/\/ do more stuff while task is running\r\n        task.Wait();\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        Console.WriteLine(\"HandleExceptionTryCatchWait: exception handled in try catch block. Exception is {0}\", ex);\r\n    }\r\n}\r\n<\/pre>\n<p>However accessing <i>Result<\/i> or calling <i>Wait<\/i> method are blocking calls, so this might not be a perfect solution for every scenario. Fortunately we can also leverage <i>ContinueWith<\/i> method which gives you an ability to specify what should be done once <i>Task<\/i> finishes processing the operation. What is more important you can configure this method to only be called if exception occurs. Nonetheless there is one crucial thing you have to remember &#8211; in order to make exception handled or observed you have to access <i>Exception<\/i> property of <i>Task<\/i>&#8230;<\/p>\n<pre>\r\npublic static void HandleExceptionContinueWith()\r\n{\r\n    Task.Factory.StartNew(() => { throw new Exception(\"From method HandleExceptionContinueWith\"); })\r\n                .ContinueWith(val =>\r\n                {\r\n                    \/\/ we need to access val.Exception property otherwise unobserved exception will be thrown\r\n                    \/\/ ReSharper disable once PossibleNullReferenceException\r\n                    foreach (var ex in val.Exception.Flatten().InnerExceptions)\r\n                    {\r\n                        Console.WriteLine(\"HandleExceptionContinueWith: exception handled in ContinueWith. Exception is {0}\", ex);\r\n                    }\r\n                }, TaskContinuationOptions.OnlyOnFaulted);\r\n}\r\n<\/pre>\n<p>or call <i>Handle<\/i> method from <i>AggregateException<\/i> object<\/p>\n<pre>\r\npublic static void HandleExceptionContinueWithAndHandleMethod()\r\n{\r\n    Task.Factory.StartNew(() => { throw new Exception(\"From method HandleExceptionContinueWith\"); })\r\n                .ContinueWith(val =>\r\n                {\r\n                    val.Exception.Handle(ex =>\r\n                    {\r\n                        Console.WriteLine(\"HandleExceptionContinueWith: exception handled in AggregateException.Handle. Exception is {0}\", ex);\r\n                        return true;\r\n                    });\r\n                }, TaskContinuationOptions.OnlyOnFaulted);\r\n}\r\n<\/pre>\n<p>Otherwise exception will not be handled which may cause a lot of troubles described in section 3 of this post. Lastly if you use <i>.NET 4.5<\/i> you can also just use <i>async await<\/i> and <i>try catch<\/i> block<\/p>\n<pre>\r\n\/\/ called from Main\r\npublic static async void HandleExceptionTryCatchAwait()\r\n{\r\n    try\r\n    {\r\n        await HandleExceptionTryCatchAwaitInternal();\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        Console.WriteLine(\"HandleExceptionTryCatchAwait: exception handled in try catch block\");\r\n    }\r\n}\r\n\r\nprivate static async Task<int> HandleExceptionTryCatchAwaitInternal()\r\n{\r\n    return await Task.Factory.StartNew(() =>\r\n    {\r\n        throw new Exception();\r\n        return 1;\r\n    }, TaskCreationOptions.LongRunning);\r\n}\r\n<\/pre>\n<h3>3. Handling UnobservedTaskException<\/h3>\n<p>If it happens that exception thrown by <i>Task<\/i> is not handled, once the <i>Task<\/i> is garbage-collected, finalizer thread will throw <i>UnobservedTaskException<\/i>.<\/p>\n<pre>\r\nTask.Factory.StartNew(() => { throw new Exception(\"fire-and-forget no exception handling\"); });\r\nusing (var autoresetEvent = new AutoResetEvent(false))\r\n{\r\n    \/\/wait for task to run\r\n    autoresetEvent.WaitOne(TimeSpan.FromSeconds(2));\r\n}\r\n\r\nConsole.WriteLine(\"GC: Collecting\");\r\nGC.Collect();\r\nGC.WaitForPendingFinalizers();\r\nConsole.WriteLine(\"GC: Collected\");\r\n<\/pre>\n<p>The implication of this depends on framework we are running our application on. If you run your app on <i>.NET 4.5<\/i> or later version, with default escalation policy, <i>TaskScheduler.UnobservedTaskException<\/i> event will be raised and basically that is all. No more further problems, so basically you may not even realize that there is something like <i>UnobservedTaskException<\/i>. However if we add this entry<\/p>\n<pre lang=\"xml\">\r\n<runtime>\r\n    <ThrowUnobservedTaskExceptions enabled=\"true\"\/>\r\n<\/runtime>\r\n<\/pre>\n<p>to <i>app.config<\/i>our process will be killed once <i>UnobservedTaskExceptionis<\/i> is thrown.<br \/>\n<a href=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2015\/08\/tpl-exception-handling-and-unobservedtaskexception-issue\/ProcessKilled.png\" rel=\"attachment wp-att-257\"><img decoding=\"async\" src=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2015\/08\/tpl-exception-handling-and-unobservedtaskexception-issue\/ProcessKilled.png\" alt=\"UnobservedTaskExceptionis\" width=\"800\" class=\"aligncenter size-full wp-image-257\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2015\/08\/tpl-exception-handling-and-unobservedtaskexception-issue\/ProcessKilled.png 801w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2015\/08\/tpl-exception-handling-and-unobservedtaskexception-issue\/ProcessKilled-150x66.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2015\/08\/tpl-exception-handling-and-unobservedtaskexception-issue\/ProcessKilled-300x132.png 300w\" sizes=\"(max-width: 801px) 100vw, 801px\" \/><\/a><br \/>\nThe problem arises in <i>.NET 4.0<\/i> (if you run your app on <i>.NET 4.0<\/i> not only compile it against this framework version), in this version of framework default escalation policy is very strict and will kill our process once the <i>UnobservedTaskException<\/i> is thrown by finalizer thread. Furthermore you cannot change this policy using <i>app.config<\/i>. Fortunately there is a one last chance to handle UnobservedExceptions and prevent our process from being killed. All you have to do is to wire up <i>TaskScheduler.UnobservedTaskException<\/i> static event handler and then set exception to observed state<\/p>\n<pre>\r\nTaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;\r\nprivate static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)\r\n{\r\n    e.SetObserved();\r\n}\r\n<\/pre>\n<p>There is one more thing to clarify. You can compile your library against <i>.NET 4.0<\/i> but if you have <i>.NET 4.5<\/i> installed on your machine, your application is launched and run on <i>.NET 4.5<\/i>. This means that escalation policy from <i>.NET 4.5<\/i> will be used &#8211; so by default process will not be killed. In order to simulate pure <i>.NET 4.0<\/i> behavior while having <i>.NET 4.5<\/i> installed you have to add<\/p>\n<pre lang=\"xml\">\r\n<runtime>\r\n    <ThrowUnobservedTaskExceptions enabled=\"true\"\/>\r\n<\/runtime>\r\n<\/pre>\n<p>in your <i>app.config<\/i> as it was mentioned before. Otherwise you would have to uninstall <i>.NET 4.5<\/i> in order to, for example reproduce production issue. Source code for this post can be found <a href=\"https:\/\/github.com\/tpodolak\/Blog\/tree\/master\/HandlingUnobservedTaskExceptions\">here<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction Working with Tasks is a modern way of writing asynchronous code in an easy and flexible manner. It is quite straightforward to start using them, so usually developers do not investigate thoroughly the topic. Unfortunately this often leads to unpleasant surprises &#8211; especially when it comes to exception handling. Having this in mind [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,8,7,10],"tags":[162,163,164,165],"class_list":["post-6","post","type-post","status-publish","format-standard","hentry","category-net-4-0","category-net-4-5","category-tpl","category-unobservedtaskexception","tag-net-4-0","tag-net-4-5","tag-tpl","tag-unobservedtaskexception"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=6"}],"version-history":[{"count":12,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/6\/revisions"}],"predecessor-version":[{"id":520,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/6\/revisions\/520"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=6"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=6"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}