Async Controller in MVC

by Sachin Singh


Posted on Saturday, 04 April 2020

Tags: Asynchronous controller in asp.net mvc example What is asynchronous controller in asp.net mvc Using asynchronous controller in asp.net mvc application Async controllers in asp.net mvc Async Controller in MVC Thread starvation problem solution in mvc How async controller solves thread starvation

In the software world currently executing a code block or program is called a task, In the Asp.Net framework, every task is handled by a thread called as main thread until you do not assign a new thread to handle the task (multi-threading). The IIS web server has a thread pool that actually allots threads to any task to execute it.

Everything in the world is limited, isn't it? so, how do you think the thread pool will have unlimited threads. The thread pool also has limited threads. The situation, when all the threads are in use and for any new task, there is no thread left in a thread pool, is called Thread Starvation.

Async controller solves the thread starvation problem. Let's take an example of thread starvation and see how Async Controller solves it.

Suppose, we have to design a user dashboard where a user can check the list of his friends, the List of his posts to date, and the List of Questions he has ever asked like the below diagram.
User Dashboard
User dashboard

Now ,let's understand how the above requirement can create thread starvation problem.

Suppose we have Dashboard view model and And ActionMethods Like below.


   public class DashboardViewModel
    {
        public List<friend> Friends { get; set; }
        public List<question> Questions { get; set; }
        public List<post> Posts { get; set; }
    }


         public ActionResult Dashboard()
         {
            Task<List<friend>> t1 = Task.Factory.StartNew(() => GetFriends());
            Task<List<question>> t2 = Task.Factory.StartNew(() => GetQuestions());
            Task<List<post>> t3 = Task.Factory.StartNew(() => GetPosts());
            Task.WhenAll(t1,t2,t3);
            DashboardViewModel dvm = new Models.DashboardViewModel();
            dvm.Friends = t1.Result;
            dvm.Questions = t2.Result;
            dvm.Posts = t3.Result;
           
            return View(dvm);
        }
        public  List<friend> GetFriends()
        {
            List<friend> frs=new List<friend>();
            Thread.Sleep(5000);
            return frs;
        }
        public List<question> GetQuestions()
        {
            List<question>ques = new List<question>();
            Thread.Sleep(5000);
            return ques;
        }
        public List<post> GetPosts()
        {
            List<post> posts = new List<post>();
            Thread.Sleep(5000);
            return posts;
        }


As soon as the Dashboard Action method is invoked a new thread called main thread is allotted to it by thread pool, then for task t1, task t2, and task t3 three more threads are allotted to serve corresponding tasks until all the tasks get completed main thread hangs in the air and does nothing, Threads are limited so any hanging thread is not good. In a multi-user scenario, there may come a situation when the count of hanging thread becomes too many and for a new task, no thread is left to serve it. Thus, it creates thread starvation.

The solution is to release the thread which is hanging and waiting for results to come. Async controller does the same, it let the waiting thread free to serve a new task. Now Let's implement Async Controller and check how it solves the thread starvation problem.

To make a controller Async following are the 4 steps.
  1. Inherit your controller from AsyncController.
  2. Change your Action Method to return Task instead of ActionResult.
  3. Mark your Action Method with async keyword.
  4. Mark the method which waits for result with await keyword.

Async Controller
Async Controller

Now, as soon as the execution flow reaches to the method marked with the await keyword the main thread gets released, hence the thread starvation is solved.