Introduction
As we know asynchronous programming is used to improve the performance and responsiveness of an application. A typical example is when we click a save
button on a web page and wait for the records to be saved to the database. If the save method is called synchronously as in a traditional web application the application
will stop responding. This is an ideal place to use asynchronous programming. That’s why we use AJAX to make asynchronous calls to the server so that when the browser
makes a request to the web server the page is not blocked. If you have a method that takes a reasonable amount of time to execute then it’s always better to call it asynchronously.
So performance and responsiveness are good enough reasons to convince us to use asynchronous programming.
Background
So we are convinced to use asynchronous programming in our application but then the main obstacle in our way to implement asynchrony in
our application is the learning curve involved as traditional asynchronous programming techniques like the Event
Based Asynchronous approach were hard to implement .Though later the abstractions like the Backgroundworker component made it easier to implement asynchrony in our
application but still programming using these is not intuitive and produces lots of cluttered code.
Compared to the traditional asynchronous approaches the new asynchronous programming model in .NET 4.5 is way cleaner and involves just three main concepts await
,async and Task. The await and async
are the keywords introduced in C# 5.0 while Task is a type in the System.Threading.Tasks
namespace used for parallel programming. We use task in asynchronous programming to specify the return type of a method. The real beauty of this new
approach is that you can write an asynchronous program just as you would write a normal sequential program. async is
used to mark a method as being executed asynchronously while await signals that the method is waiting for some processing to complete, like a
method call, and cannot continue till that other method completes processing.
So we use this same concept in MVC for requests with high latency. Just for a quick review let’s see how ASP.NET processes a new request. ASP.NET has a pool of threads to service requests, when a new request comes a new thread is picked from the thread pool to service the request. Now this
thread that is selected to serve the request cannot serve any other request until the initial request completes. And if this request has a high latency,
such as a network operation, then the thread is also blocked until the request finishes execution. So assuming that there are a lot of concurrent high latency
calls majority of the threads will be just blocked waiting for the request to finish. So as majority of the threads are just waiting and not doing any processing
most of the time, the threads can be better utilized by using asynchronous programming.
In the .NET 4.5 the default maximum size of the thread pool is 5, 000 threads. Though we can extend the size of
this thread pool but still the fact is that there is still some limit of the max ThreadPool size and it is always nice not
to exhaust this limit of the ThreadPool
.
It’s simple to implement asynchronous action methods using the await and async keywords in.NET
4.5.Let’s see how we can implement an action method that makes a network call first using the normal sequential approach and then using the new asynchronous
programming approach using the async and await keywords.
The following action method we have implemented returns a List of employees from the database using a service call. Since fetching all the
employees may take a considerable amount of time we can implement this action method as an asynchronous method.
In the above method the control does not return back to the calling method until the GetEmployees()
web service
method completes execution. We can avoid this wait time by implementing the action method asynchronously as below.
If you observe there are only three differences in the asynchronous and synchronous action methods.
- In the asynchronous method we are wrapping the return type in a Task while in a normal synchronous method we just return an
ActionResult
type.
- The asynchronous method uses the
async
keyword in its declaration.
- The asynchronous method uses the
await
keyword while making a method call that is expected to take a while to complete.
If you think that the action method may take to long to execute you can set the timeout using the AsyncTimeout
which sets the
timeout period in milliseconds. Following method signature sets the timeout of the action method to 200 milliseconds.
[AsyncTimeout(200)]
public async Task<ActionResult> GetEmployeesAsync()
So suppose there is an action method that takes a long time to execute ,implementing the action method asynchronously will not
reduce the time much as compared to the synchronous version of the same method. The difference is that the asynchronous approach will just not keep the action
method blocked for the time period it is waiting for the call to the external resource like a network call or a database call to complete.
Rather than expecting that implementing the asynchronous action methods will always result in performance improvement it’s always better
to evaluate the scenario and the requirement. Implementing asynchronous action methods will bring performance improvement in the following cases:
When there are long running action methods or action methods that are CPU or network intensive.
When you have a multicore system and want to use parallelism to improve the application performance.
So if you have an application that has a lot of concurrent calls that are network or CPU bound using the asynchronous approach will definitely result in performance improvement.