Synchronous vs asynchronous MVC controllers

Advantage of using asynchronous over synchronous controller in MVC

  • Share

Maybe you did not know but asp.net applications have limited number of threads available to process requests.

This value is set in your machine.config in configuration/system.web/processModel node. This file is located at

32-bit
%windir%\Microsoft.NET\Framework\[version]\config\machine.config

64-bit
%windir%\Microsoft.NET\Framework64\[version]\config\machine.config

<processModel 
   maxWorkerThreads="num"
   maxIoThreads="num"
   minWorkerThreads="num"
   minIoThreads="num"
   ...
   />
    

If these values are not set in machine.config the default values are used. Default values for machine.config you can find at MSDN http://msdn.microsoft.com/en-us/library/7w2sway1(v=VS.100).aspx

Usually your app does not reach maximum number of threads for your web app to handle requests sent to your app, but if your app depends on some external resource, let's say you are pulling values from Facebook or Twitter. These operations may take some time, so one of your threads will be busy waiting for a response from the external resource which it invoked.

You probably will not run into a problem if your web application does not have many IO threads which take a lot of time. The real performance impact can be noticed during a high traffic.

This is when async controllers come into the play. Basically you can split your long time operations into multiple threads and get back to working thread when long operation is over. The good thing is that it is really easy to transform your synchronous controller action to async and I'm about to show it in the next example.

In the following method we will simulate some long time operation with simple anonymus method which puts thread to sleep for 1000 miliseconds

    public class SyncController : ApiController
    {
        public string get()
        {
           return new Func<string>(() =>
            {
                Thread.Sleep(1000);
                return "done";
            })();
        }
    }
    

While waiting for a response, this action will keep working thread occupied. The following is the same method but with the async operation.

    public class AsyncController : ApiController
    {
        public async Task<string> get()
        {
            return await new Task<string>(() =>
            {
                return new Func<string>(() =>
                {
                    Thread.Sleep(1000);
                    return "done";
                })();

            });
        }
    }
    

Async controllers are really good thing for optimizing your web application, but it does not mean that you need to rewrite all your controllers in existing applications just to make them async. If controller action does not use any remote resource or some complex logic which takes time or large IO operation, you are pretty good with sync controllers.

But this is not where usage of async controller ends. Imagine you have to pull not only data for Facebook posts, but also you need to pull tweets from Twitter API. You can make multiple tasks from one call and tell invoking working thread to wait for all sync actions to complete before it goes back to working thread.

Unfortunately I don have Ultimate version of Visual Studio to show you the results of a test, but if you do you can create Web Performance and Load Test Project and test both controller actions and see the difference.

  • Share

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.

Comments for this article

comments powered by Disqus