{"id":116,"date":"2022-02-06T19:01:38","date_gmt":"2022-02-06T19:01:38","guid":{"rendered":"https:\/\/baldsolutions.com\/?p=116"},"modified":"2022-02-06T19:06:59","modified_gmt":"2022-02-06T19:06:59","slug":"async-eliding-part-2-drawbacks","status":"publish","type":"post","link":"https:\/\/baldsolutions.com\/index.php\/2022\/02\/06\/async-eliding-part-2-drawbacks\/","title":{"rendered":"Async eliding, part 2 \u2013 drawbacks"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\" id=\"introduction\">Introduction<\/h1>\n\n\n\n<p>In the previous <a href=\"https:\/\/baldsolutions.com\/index.php\/2022\/01\/30\/async-eliding-part-1-benefits\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"post\">post<\/a> I described the benefits regarding async eliding: performance and allocation (of course by using benchmark as a proof &#8211; let us be clear, no benchmark no proof).  In this post I will show you that async eliding is not as sweet, great, perfect and lovely and it might seem to be. Let&#8217;s get to the point!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"http-crash\">HTTP crash<\/h1>\n\n\n\n<p>Firstly, I must truly apologise you. The heading is kind of a bait&#8230; not 100% though but still. Async eliding can cause the HTTP crash but it is not limited to it &#8211; I will just use it as an example. Let&#8217;s consider the following example:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>public class HttpClientExecutor\n{\n    private readonly string _uri= \"https:\/\/postman-echo.com\/get?foo1=bar1&amp;foo2=bar2\";\n\n    public async Task&lt;string&gt; GetWithUsingAndWithoutEliding()\n    {\n        using var _httpClient = new HttpClient();\n        return await _httpClient.GetStringAsync(_uri);\n    }\n\n    public Task&lt;string&gt; GetWithUsingAndWithEliding()\n    {\n        using var _httpClient = new HttpClient();\n        return _httpClient.GetStringAsync(_uri);\n    }\n}<\/code><\/pre>\n\n\n\n<p>The first method, i.e. <code>GetWithUsingAndWithoutEliding<\/code>, creates the <code>httpClient<\/code> and gets the response from the provided uri. The <code>httpClient<\/code> is then disposed. By the way, this is not the best approach of the <code>HttpClient<\/code> usage because of the socket exhaustion (probably the best approach now is to use the <a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/fundamentals\/http-requests?view=aspnetcore-6.0\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"IHttpClientFactory\">IHttpClientFactory<\/a>), but it shows one of the async eliding problems.<\/p>\n\n\n\n<p>Does the second method, i.e. <code>GetWithUsingAndWithEliding<\/code>, do the same?<\/p>\n\n\n\n<p>Well yes, but actually no. The <code>HttpClient<\/code> is instantiated within the using statement and the <code>GetStringAsync<\/code> method is invoked, but then the <code>TaskCanceledException <\/code>would be thrown. It happens because the <code>httpClient<\/code> is disposed during the HTTP GET request processing.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"exceptions\">Exceptions<\/h1>\n\n\n\n<p>This time the heading is 100% not a bait. To give some concrete examples let&#8217;s consider the following example:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>public class ExceptionExecutor\n{\n    public async Task&lt;int&gt; DivideWithoutEliding(int dividend, int divider)\n    {\n        var result = dividend \/ divider;\n        return await Task.Run(() =&gt; result);\n    }\n\n    public Task&lt;int&gt; DivideWithEliding(int dividend, int divider)\n    {\n        var result = dividend \/ divider;\n        return Task.Run(() =&gt; result);\n    }\n}<\/code><\/pre>\n\n\n\n<p>If you&#8217;ve just thought about DivideByZeroException, then you are absolutely right, it will be thrown in a moment, but the point is in what circumstances? To understand the difference please open in a separate tab <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/blob\/master\/.NET\/async-eliding-part-2-tests\/ExceptionExecutorTests.cs\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"tests\">tests<\/a> that I&#8217;ve prepared for this (I could have pasted it here but it would have produced to much noise). <\/p>\n\n\n\n<p>Let&#8217;s focus on the <code>DivideWithoutEliding_DividerIsZeroAndAndAssignTaskToTheVariableFirst_WhenAwaitThrowsDivideByZeroException<\/code> and <code>DivideWithEliding_DividerIsZeroAndAssignTaskToTheVariableFirst_WhenAssignToTheVariableThrowsDivideByZeroException<\/code>tests. The first one throws the exception  NOT when we assign to the <code>task<\/code> variable but when we await it. The second one throws the exception when we assign to the <code>task<\/code> variable. It happens because when we do the classic async\/await approach (not elided) the exception is packed in the returned Task. On the other hand, when we do the async eliding, the exception is thrown before we use the await keyword.<\/p>\n\n\n\n<p>Why would we want to assign Task to the variable and then await it?  <\/p>\n\n\n\n<p>We can think of a scenario where we want to run 3 tasks and waits for any of them to complete, in other words we want to use <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.threading.tasks.task.whenany?view=net-6.0\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Task.WhenAny\">Task.WhenAny<\/a>. Let&#8217;s add two methods to the <code>ExceptionExecutor<\/code> class:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>public async Task&lt;Task&lt;int&gt;&gt; DivideMany_WithoutEliding(int dividend, int divider)\n{\n    var task1 = DivideWithoutEliding(dividend, divider);\n    var task2 = DivideWithoutEliding(dividend, divider);\n    var task3 = DivideWithoutEliding(dividend, divider);\n\n    return await Task.WhenAny(result1, result2, result3);\n}\n\npublic async Task&lt;Task&lt;int&gt;&gt; DivideMany_WithOneEliding(int dividend, int divider)\n{\n    var task1 = DivideWithoutEliding(dividend, divider);\n    var task2 = DivideWithoutEliding(dividend, divider);\n    var task3 = DivideWithEliding(dividend, divider);\n\n    return await Task.WhenAny(task1, task2, task3);\n}<\/code><\/pre>\n\n\n\n<p>There are two tests that show the behaviour of such a scenario:<code>DivideMany_WithoutEliding_DividerIsZero_WhenAwaitSecondThrowsDivideByZeroException<\/code> and <code>DivideMany_WithOneEliding_DividerIsZero_WhenFirstAwaitThrowsDivideByZeroException<\/code>. <\/p>\n\n\n\n<p>As always I&#8217;ve prepared an example and you can find it on my <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\">github<\/a>, project: async-eliding-part-2, test project: async-eliding-part-2-tests. I encourage you to go through the code, debug it and try to test your own scenarios. Unfortunately, I haven&#8217;t prepare any benchmark this time, but I attach great <a href=\"https:\/\/blog.stephencleary.com\/2016\/12\/eliding-async-await.html\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"article \">article <\/a>to read about the async eliding.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"summary\">Summary<\/h1>\n\n\n\n<p>Async eliding is an interesting approach. On the one hand it can improve the performance and the allocation, but on the other hand the program behaviour changes which can cause to the unexpected application errors. Recommended way of using async eliding is not to use it, unless you have a really good reason to boost some of the hot paths` performance of your application and, above all, you are aware of the potential consequences.<\/p>\n\n\n\n<p>Have a nice day, bye!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In the previous post I described the benefits regarding async eliding: performance and allocation (of course by using benchmark as a proof &#8211; let&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/baldsolutions.com\/index.php\/2022\/02\/06\/async-eliding-part-2-drawbacks\/\">Continue reading<span class=\"screen-reader-text\">Async eliding, part 2 \u2013 drawbacks<\/span><\/a><\/div>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-116","post","type-post","status-publish","format-standard","hentry","category-net","entry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/comments?post=116"}],"version-history":[{"count":13,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":137,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/116\/revisions\/137"}],"wp:attachment":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/media?parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/categories?post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/tags?post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}