{"id":1398,"date":"2012-09-12T00:00:00","date_gmt":"2012-09-12T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/asp-net-go-async-or-sink\/"},"modified":"2021-05-17T18:34:58","modified_gmt":"2021-05-17T18:34:58","slug":"asp-net-go-async-or-sink","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/asp-net-go-async-or-sink\/","title":{"rendered":"ASP.NET: Go Async or Sink"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">For server-based applications, asynchronous operations are fundamental to scalability. So important for web applications is it that Microsoft have made asynchronous HTTP handlers available since ASP.NET 1.0. An asynchronous HTTP handler is a component that implements the <strong>IHttpAsyncHandler<\/strong> interface. The <strong>IHttpAsyncHandler<\/strong> interface extends the more popular <strong>IH<\/strong><strong>ttpHandler<\/strong> interface by adding a pair of begin\/end methods to process the request. Here&#8217;s a basic skeleton of an asynchronous HTTP handler. <\/p>\n<pre class=\"prettyprint\">public class SampleHandler : IHttpAsyncHandler\n{ \n   private WorkerDelegate _delegate;\n   protected delegate void WorkerDelegate(HttpContext context);\n   public IAsyncResult BeginProcessRequest(\n         HttpContext context, AsyncCallback cb, object extraData) \n   { \n     _delegate = new WorkerDelegate(ProcessRequest);\n      return _delegate.BeginInvoke(context, cb, extraData);\n   } \n\n   public void EndProcessRequest(IAsyncResult result) \n   { \n     _delegate.EndInvoke(result);\n   } \n   \n   public bool IsReusable\n   { \n     get { return true; } \n   } \n\n   public void ProcessRequest(HttpContext context) \n   { \n     \/\/ Do the actual processing for the request \n     :\n   } \n}<\/pre>\n<p>As you can see, except for the body of <strong>ProcessRequest<\/strong>, the code of the class <strong>SampleHandler<\/strong> is boilerplate code. Over the years, however, both ASP.NET Web Forms and ASP.NET MVC have come to provide their own facilities to make it simpler for developers to implement HTTP handlers asynchronously. In particular, ASP.NET MVC has provided asynchronous controllers since version 2. Asynchronous controllers are even easier to implement with the latest release-ASP.NET MVC 4-thanks to some additional syntactic sugar in the C# language. <\/p>\n<p>Before we delve deeper into the implementation of asynchronous controllers in ASP.NET MVC, let&#8217;s pinpoint why asynchronous operations are critical in server-side ASP.NET. <\/p>\n<h2>It&#8217;s All About Site Performance <\/h2>\n<p>Everybody would agree that asynchronously-served requests are important for the performance of potentially-lengthy operations. Taking this point to the limit, Windows 8 is highly dependent upon asynchronous operations and that is the preferred way of coding in the newest platform. <\/p>\n<p>What exactly does <em>performance<\/em> mean in this context? Is it about serving the page (or data) to the client in a faster way? Is it about keeping the user interface responsive while the request is going on? As surprising as it may sound, the main point of asynchronous ASP.NET requests is neither of these. <\/p>\n<p>From the user&#8217;s perspective, it will take the same time to complete a request whether it runs synchronously or asynchronously. Suppose that a given request triggers a server-side process that takes, say, 30 seconds. Well, the request won&#8217;t take less than 30 seconds to complete regardless of you using a plain HTTP handler or an asynchronous handler. Moreover, it may even be that the async operation takes a bit longer to complete. <\/p>\n<p>What about the other point-the more responsive user interface? <\/p>\n<p>The user experience determined by using an async model shines in rich client environment such as desktop Windows or Windows Phone applications where the application remains responsive while the lengthy tasks progresses. In a web scenario, there&#8217;s no difference at all if you fully refresh the page. If you use Ajax, instead, then your page will be highly responsive anyway, whether the request is synchronous or not. <\/p>\n<p>So what&#8217;s the real benefit of implementing asynchronous requests? <\/p>\n<p>The benefits of asynchronous requests are entirely for the server environment. In ASP.NET, async HTTP handlers keep the server runtime much more responsive by guaranteeing that a larger number of threads are available at any time to serve requests. In the end, it won&#8217;t so much be the requests for long-running tasks that benefit from async handlers, but all other requests, for images, scripts, and other static and ASPX pages. In this way, the site remains highly responsive for all users and long-running requests will still take their time to complete. <\/p>\n<h2>Async Management of ASP.NET Threads<\/h2>\n<p>ASP.NET serves requests by assigning them to threads picked up from the ASP.NET thread-pool. Requests are therefore served promptly as long as there are threads available. Suppose now that the site exposes several long-running operations and receives a lot of requests for these operations. Suppose, too, that each long-running request is implemented synchronously. This means that each long-running operation keeps a thread blocked for all the time it takes to complete the operation. With many of long-running operations pending, the number of free threads in the pool will diminish and requests will become more likely to be queued. Then, when the queue finally fills up, users start receiving error messages for unavailable server. <\/p>\n<p>What&#8217;s exactly a long-running operation? <\/p>\n<p>There are two types of long-running operations; the CPU-bound and the I\/O-bound. A CPU-bound operation takes a while to complete because the CPU (or one of its cores) has a lot of work to do. Think for example of a complex statistic algorithm; the thread will take a while to return simply because it&#8217;s doing work. An I\/O-bound operation on the other hand, is subject to I\/O latency. In this case, the operation takes a while because its completion depends on data being received, or sent, to external devices. The running thread cannot return until the task is complete, but all it does is wait. A great example of an I\/O-bound operation is invoking a web endpoint. <\/p>\n<p>An Async programming model will efficiently solve any scalability problems that are caused by I\/O-bound operations. A CPU-bound operation, on the other hand, is a true bottleneck: the operation can&#8217;t be avoided if you need its results but it keeps a thread blocked. To minimize the impact of CPU-bound operations you should try to transform it in a I\/O-bound operation. This means that request be forwarded to a worker thread as it happens in code snippet we went through at the beginning of the article. Async programming therefore is essential. Just to give more the sense of importance of async programming, consider that, in Windows 8 and earlier in Windows Phone, Microsoft considers any operation to be a long-running operation that takes more than just a few milliseconds to complete. <\/p>\n<p>Although it is only recently that Async programming has become publicised, the basic tools for async programming in ASP.NET have always been there. Let&#8217;s see how an async HTTP handler makes several I\/O bound operations sustainable and thereby preserves scalability. <\/p>\n<p>An async HTTP handler features two methods-<strong>BeginProcessRequest<\/strong> and <strong>EndProcessRequest<\/strong><strong>.<\/strong> This means that each request executes in two non-consecutive steps. Each step requires its own ASP.NET thread. More often than not, the two steps of the same request are carried over by different ASP.NET threads. When the request comes in, one ASP.NET thread picks it up and executes it up until the end of <strong>BeginProcessRequest<\/strong> which is when you start the potentially lengthy operation such as invoking a remote web service. At this point, the original ASP.NET thread is released to the pool and made ready to serve another incoming request. Who does take care of waiting for the long-running operation to complete? As software is not magic, we do need some other thread to wait for that. <\/p>\n<p>To deal with this, ASP.NET comes with two thread pools-the popular ASP.NET thread pool and the less known completion port thread pool (CPTP). Threads in the first pool manage incoming requests; threads in the second pool just manage the wait for I\/O-bound operations. In the end, when an async operation ends the first step then ASP.NET performs a sort of thread switch: It picks up a thread from the CPTP and makes it wait. The completion of the long-running operation is internally associated with a callback that, once signaled, adds a new fake request to the ASP.NET queue to complete the previous request. At that point, the first free thread in the ASP.NET pool will pick it up and run<strong>EndProcessRequest<\/strong>. (See Figure 1.) <\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1555-12ccd2cb-f076-4c12-920e-6fa8ca6e64c1.png\" alt=\"1555-12ccd2cb-f076-4c12-920e-6fa8ca6e64c\" \/><\/p>\n<p><strong>Figure 1.<\/strong><strong> Async HTTP request processing in ASP.NET.<\/strong> <\/p>\n<p>In ASP.NET Web Forms, this machinery is hidden inside asynchronous pages; in ASP.NET MVC, instead, you have the<strong>AsyncController<\/strong> class. <\/p>\n<h2>The AsyncController Class<\/h2>\n<p>In ASP.NET MVC, you start implementing asynchronous operations for potentially lengthy tasks by deriving your controller class from AsyncController. Note that an AsyncController class can serve both synchronous and asynchronous requests. The name of the method conventionally indicates how the method has to be processed by the runtime. An asynchronous action is implemented using a pair of methods aptly named to clearly indicate <em>begin<\/em> and <em>completion<\/em> steps. For example, a method GetLatestNews is implemented asynchronously as below: <\/p>\n<pre class=\"prettyprint\">public class SampleAsyncController : AsyncController\n{\n  public void GetLatestNewsAsync(ModelBindingData data) \n  {\n     ... \n  }\n  public ActionResult GetLatestNewsCompleted(LongRunningTaskResponse data) \n  {\n     ... \n  }\n}<\/pre>\n<p>The <strong>xxxAsync<\/strong> method represents the beginning of the request-processing and it ends by triggering the long-running process. The <strong>xxxCompleted<\/strong> method represents the completion of the operation when data from the long-running process has been acquired, and it just remains to finalize the ASP.NET request. It is not a coincidence that <strong>xxxAsync<\/strong> is void whereas <strong>xxxCompleted<\/strong> returns an<strong>ActionResult<\/strong> object. Also, note that model binding takes place on the <strong>xxxAsync<\/strong>method, whereas <strong>xxxCompleted<\/strong>receives any data that is relevant for the completion of the request. <\/p>\n<p>It is important to note that if another method named <strong>xxx<\/strong> exists in the same controller class, and is not disambiguated by using HTTP verb or action name attributes, then an exception is thrown. For example, the following code won&#8217;t work: <\/p>\n<pre class=\"prettyprint\">public class SampleAsyncController : AsyncController\n{\n  \/\/ This is method \"GetLatestNews\" run synchronous\n  public ActionResult GetLatestNews(ModelBindingData data) \n  {\n     ... \n  }\n\n  \/\/ This is method \"GetLatestNews\" run asynchronously\n  public void GetLatestNewsAsync(ModelBindingData data) \n  {\n     ... \n  }\n  public ActionResult GetLatestNewsCompleted(LongRunningTaskResponse data) \n  {\n     ... \n  }\n}<\/pre>\n<p>Let&#8217;s see more details about the code you might want to have within <strong>xxxAsync<\/strong> and <strong>xxxCompleted<\/strong>. <\/p>\n<h2>Async Actions <\/h2>\n<p>The implementation of <strong>xxxAsync<\/strong> and <strong>xxxCompleted<\/strong> requires a bit of care as there are some common steps to be accomplished. In <strong>xxxAsync<\/strong> you need, first and foremost, to increase the count of pending asynchronous operations. Next, you add the code, being careful to use a method from the .NET Framework classes designed for async behavior. For example, if you need to make a HTTP server side request you use <strong>DownloadStringAsync<\/strong> from the <strong>WebClient<\/strong> class: <\/p>\n<pre class=\"prettyprint\">public void GetLatestNewsAsync(SomeData data) \n{\n    AsyncManager.OutstandingOperations.Increment();\n\n    \/\/ Do some remote work (for example, invoke a service)\n    var client = new WebClient();\n    client.DownloadStringCompleted += (sender, e) =&gt;\n                {\n                   \/\/ Raw data downloaded\n                   var data = e.Result;\n\n                   \/\/ Package data for the \"completed\" method\n                   AsyncManager.Parameters[\"RawResponse\"] = data;\n                   ...    \n\n                   \/\/ Terminate operations, and prepare data for the \"completed\" method\n                   AsyncManager.OutstandingOperations.Decrement();                                                   \n                };\n    client.DownloadStringAsync(uri);\n}<\/pre>\n<p>Finally, you decrement the count of pending operations when you&#8217;re done. Any data you downloaded should, reasonably, be passed to the <strong>xxxCompleted<\/strong> method to be packaged into a view model or a JSON string and returned to the browser. You use the Parameters collection of the <strong>AsyncManager<\/strong> object to do this. Here is a possible implementation of the <strong>xxxCompleted<\/strong> method: <\/p>\n<pre class=\"prettyprint\">public ActionResult GetLatestNewsCompleted(String rawResponse)\n{\n    return String.IsNullOrEmpty(rawResponse)\n                ? (ActionResult)new HttpNotFoundResult()\n                : Json(rawResponse, JsonRequestBehavior.AllowGet);\n}<\/pre>\n<p>Note that parameters in the signature of <strong>xxxCompleted<\/strong> are subject to the same model binding rules as parameters received within the HTTP request. <\/p>\n<h2>Async Methods and Attributes<\/h2>\n<p>In ASP.NET MVC, you can apply several action filter attributes to controller methods. You should place any applicable attributes for an asynchronous method on the trigger method <strong>xxxAsync<\/strong>. Note that attributes applied to the <strong>xxxCompleted<\/strong> method will be ignored. If an <strong>ActionName<\/strong> attribute is placed on <strong>xxxAsync<\/strong> to alias it, then the <strong>xxxCompleted<\/strong> method must be named after the xxx name, not the action name. <\/p>\n<p>You can set a timeout on a per-controller or per-action basis by using the <strong>AsyncTimeout<\/strong> attribute. The duration is expressed in milliseconds and defaults to 30 seconds. <\/p>\n<pre class=\"prettyprint\">[AsyncTimeout(3000)]<\/pre>\n<p>By default, all methods are subject to this timeout. If you do not want any timeout, you set that preference explicitly by using the<strong>NoAsyncTimeout<\/strong> attribute. No timeout is equivalent to setting the timeout to the value of <strong>System.Threading.Timeout.Infinite<\/strong>. <\/p>\n<p>Note also that you can tweak the value of the Timeout property on the <strong>AsyncManager<\/strong> class. By doing so, you set a new global timeout value that applies to any calls unless it&#8217;s overridden by attributes at the controller or action level. <\/p>\n<h2>Summary<\/h2>\n<p>Async programming has always been there, but probably only a small subset of particularly smart developers really cared about it for years. When more and more developers started looking at async programming, it became clear that adjustments were required to the programming model. Async pages in Web Forms and async controllers in ASP.NET MVC aren&#8217;t that hard to deal with, but they definitely make async a bit annoying and subliminally spring developers to use it only when strictly required. <\/p>\n<p>The recent release of the .NET Framework 4.5 and newest version of the C# language put asynchronous programming on the spotlight and new language features really make async programming nearly undistinguishable from classic synchronous programming. There are no more excuses; go async or sink! <\/p>\n<div class=\"note\">\n<p class=\"note\"> \t<a href=\"http:\/\/www.red-gate.com\/labs\/ants-performance-profiler\/?utm_source=simpletalk&amp;utm_medium=article&amp;utm_campaign=antsperformanceprofiler&amp;utm_content=async-goasyncorsink\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1555-ANTS_60x60_Logo_CP.gif\" class=\"float-left\" alt=\"1555-ANTS_60x60_Logo_CP.gif\" \/><\/a> \tInterested in how your async code performs? ANTS Performance Profiler has an async profiling mode to help you understand where applications spend their time while doing async work. <a href=\"http:\/\/www.red-gate.com\/labs\/ants-performance-profiler\/?utm_source=simpletalk&amp;utm_medium=article&amp;utm_campaign=antsperformanceprofiler&amp;utm_content=async-goasyncorsink\">Try it out now<\/a>.<\/p>\n<\/p><\/div>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>To be scalable, web applications have always had to be asynchronous, even if the programmer did not need to be particularly aware of the fact. However ASP.NET Webforms and ASP.NET MVC now to make it simpler for developers to implement HTTP handlers asynchronously. You can also start implementing asynchronous operations for potentially lengthy tasks in ASP.NET MVC. Dino explains how. &hellip;<\/p>\n","protected":false},"author":221911,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4156,4157,5709,5166],"coauthors":[],"class_list":["post-1398","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-asp","tag-asp-net","tag-async","tag-mvc"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221911"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1398"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1398\/revisions"}],"predecessor-version":[{"id":91066,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1398\/revisions\/91066"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1398"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}