{"id":228975,"date":"2020-04-28T10:00:48","date_gmt":"2020-04-28T17:00:48","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/visualstudio\/?p=228975"},"modified":"2020-05-02T20:28:41","modified_gmt":"2020-05-03T03:28:41","slug":"exception-helper-rethrown-exceptions","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/exception-helper-rethrown-exceptions\/","title":{"rendered":"Exception Helper \u2013 Rethrown Exceptions"},"content":{"rendered":"<p>Ever had a bug in an async method that caused an exception? Been frustrated that the debugger doesn&#8217;t show you where that exception happened? Or been frustrated when looking at an exception that has an inner exception, but the debugger doesn&#8217;t easily show you where that exception was from? Starting from the Visual Studio 2019 16.5 release, the exception helper now contains the original call stack for a rethrown exception. This helps you get to the root cause in your code of any rethrown exceptions. This is especially helpful in the case of async exceptions, which are caught and then re-thrown by framework code.<\/p>\n<p><img decoding=\"async\" width=\"628\" height=\"321\" class=\"wp-image-228976 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-1.png\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-1.png 628w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-1-300x153.png 300w\" sizes=\"(max-width: 628px) 100vw, 628px\" \/><\/p>\n<p>The screenshot above is taken from a simple program that\u2019s using the \u2018await\u2019 pattern with break on thrown exceptions turned off.<\/p>\n<p><code><\/code><\/p>\n<p><code>static async Task Main(string[] args)<\/code>\n<code>        {<\/code>\n<code>\u00a0 \u00a0 await a();<\/code>\n<code>        }<\/code><\/p>\n<p><code>        async static Task&lt;string&gt; a()<\/code>\n<code>        {<\/code>\n<code>\u00a0 \u00a0 return await b();<\/code>\n<code>        }<\/code><\/p>\n<p><code>        async static Task&lt;string&gt; b()<\/code>\n<code>        {<\/code>\n<code>\u00a0 \u00a0 return await c();<\/code>\n<code>        }<\/code><\/p>\n<p><code>        async static Task&lt;string&gt; c()<\/code>\n<code>        {<\/code>\n<code>\u00a0 \u00a0 string s = null;<\/code>\n<code>\u00a0 \u00a0 return await Task&lt;string&gt;.FromResult(s.ToLower());<\/code>\n<code>        }<\/code><\/p>\n<p>In the example the exception is thrown at <em>s.ToLower()<\/em> and exception becomes unhandled at <em>await a()<\/em> and because of how await works in C# that is where the debugger stops. Unfortunately, all the useful information is back in the function <em>c<\/em>. Now with the changes in Visual Studio 2019 16.5 you can see the call stack from where the exception was originally thrown in the exception helper (screenshot below).<\/p>\n<p><img decoding=\"async\" class=\" wp-image-229095 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/ExceptionHelperSourceLinks-300x229.png\" alt=\"Image of Exception Helper with Source Links\" width=\"328\" height=\"250\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/ExceptionHelperSourceLinks-300x229.png 300w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/ExceptionHelperSourceLinks-768x587.png 768w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/ExceptionHelperSourceLinks.png 807w\" sizes=\"(max-width: 328px) 100vw, 328px\" \/><\/p>\n<p>You can click on each of the <em>Program.cs<\/em> links and navigate to the source location at the top of the call stack, inside <em>ConsoleApp5.Program.c() <\/em>in this case, and then set a breakpoint to be hit next time you run the scenario. Then when the breakpoint is hit you will be stopped at the location where the exception originated and where you probably want to debug further and potentially make changes to fix the issue.<\/p>\n<p>While you can navigate to the right source code with this feature, you can\u2019t use watches to inspect the state of the application exactly as it was when the exception was initially thrown. This is simply because other code has run since then, which could have changed the state of the application. However, if you are using Visual Studio Enterprise using Visual Studio 2019 Enterprise there is another option, IntelliTrace.<\/p>\n<h2>IntelliTrace<\/h2>\n<p>With IntelliTrace VS will capture state from your application at certain points, including when exceptions are thrown, and you can go back and inspect that previous state. The easiest way to do this is to look at the Events tab of the diagnostic tools window (it pops up on the right when you F5). In the events tab you\u2019ll see an event for each exception. In this async example each one of the async methods has a corresponding thrown and caught exception event. If you click on any of them IntelliTrace will take the debugger back to that point in time and you can use the watch windows to inspect the state as it was.<\/p>\n<p><img decoding=\"async\" width=\"450\" height=\"407\" class=\"wp-image-228977 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-2.png\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-2.png 450w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-2-300x271.png 300w\" sizes=\"(max-width: 450px) 100vw, 450px\" \/><\/p>\n<p>With most exceptions you probably want to go to the first instance as that\u2019s where it was first thrown. It\u2019s worth mentioning that not all the state is captured for every exception. Things such as the locals and parameters are, but if you were to enter new expression in the watch window it might not evaluate. If you want to capture all the state of the application, you should enable the IntelliTrace Snapshots feature. You can do that by going to Tools Options -&gt; IntelliTrace and enabling \u201cIntelliTrace snapshots (managed and native)\u201d as shown below.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-228978 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-3.png\" width=\"742\" height=\"505\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-3.png 1065w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-3-300x204.png 300w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-3-1024x697.png 1024w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2020\/04\/word-image-3-768x523.png 768w\" sizes=\"(max-width: 742px) 100vw, 742px\" \/><\/p>\n<p>With IntelliTrace Snapshots the entire state of the application is captured, and you can inspect anything in the application via the locals and watch windows.<\/p>\n<p>There are more details in our docs at <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/debugger\/view-historical-application-state?view=vs-2019\">https:\/\/docs.microsoft.com\/en-us\/visualstudio\/debugger\/view-historical-application-state?view=vs-2019<\/a>.<\/p>\n<h2>Conclusion<\/h2>\n<p>Debugging async code is challenging and something that we are committed to improving the experience of in Visual Studio. This feature is a small step on a path to improving that experience. We have more in mind for the future and would love your feedback, and to hear about the challenges you face and how features like this and others may help or not. If you\u2019re interested in taking part in customer research feel out the survey at <a href=\"https:\/\/www.research.net\/r\/3WNNWV8\">https:\/\/www.research.net\/r\/3WNNWV8<\/a>. You can also reach out to me on twitter at <a href=\"https:\/\/twitter.com\/AndySterland\">@andysterland<\/a>.<\/p>\n<p>Last, but not least, please suggest and vote on features over on Developer Community at <a href=\"https:\/\/developercommunity.visualstudio.com\/content\/idea\/post.html?space=8\">https:\/\/developercommunity.visualstudio.com\/content\/idea\/post.html?space=8<\/a>.<\/p>\n<p>Look forward to hearing your feedback!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ever had a bug in an async method that caused an exception? Been frustrated that the debugger doesn&#8217;t show you where that exception happened? Or been frustrated when looking at an exception that has an inner exception, but the debugger doesn&#8217;t easily show you where that exception was from? Starting from the Visual Studio 2019 [&hellip;]<\/p>\n","protected":false},"author":7412,"featured_media":229092,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[155],"tags":[9,3835,6153],"class_list":["post-228975","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-studio","tag-debug","tag-diagnostics","tag-exception"],"acf":[],"blog_post_summary":"<p>Ever had a bug in an async method that caused an exception? Been frustrated that the debugger doesn&#8217;t show you where that exception happened? Or been frustrated when looking at an exception that has an inner exception, but the debugger doesn&#8217;t easily show you where that exception was from? Starting from the Visual Studio 2019 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/228975","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/7412"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=228975"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/228975\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/229092"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=228975"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=228975"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=228975"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}