Tuesday, 5 June 2012

Living with async

I was watching once again The zen of async: Best practices for best performance talk of Stephen Toub’s on //Build and I decided I should blog about how easy is to end up with a deadlock while writing asynchronous code with new C# 5.0 language features (AKA async/await). Here is the quick background first which I was aware of before I watch this talk. The talk that Toub has given was mostly about how you create better reusable libraries with asynchronous language features but there are lots of great information concerning application level code.

When you are awaiting on a method with await keyword, compile generates bunch of code in behalf you. One of the purposes of this is to handle synchronization with the UI thread. The key component of this feature is the SynchronizationContext.Current which gets the synchronization context for the current thread. SynchronizationContext.Current is populated depending on the environment you are in. For example, if you are on a WPF application, SynchronizationContext.Current will be a type of DispatcherSynchronizationContext. In an ASP.NET application, this will be an instance of AspNetSynchronizationContext which is not publicly available and not meant for external consumption. SynchronizationContext has virtual Post method which dispatches an asynchronous message to a synchronization context when overridden in a derived class. When you give this method a delegate, this delegate will be marshaled back to the UI thread and invoked on that UI thread.

The GetAwaiter method (yes, "waiter" joke is proper here) of Task looks up for SynchronizationContext.Current. If current synchronization context is not null, the continuation that gets passed to that awaiter will get posted back to that synchronization context. This feature is a great feature when we are writing application level code but it turns out that if we are not careful enough, we might end up with a deadlock because of this. Here is how:



This is a part of the slide from that talk and shows how we can end up with a deadlock. Task has a method named Wait which hangs on the task till it completes. This method is an evil method in my opinion but I am sure that there is a good reason why it is provided. You never ever want to use this method. But, assume that you did use it on a method which returns a Task or Task<T> for some T and uses await inside it to await another task, you will end up with a deadlock if you are not careful. The picture explains how that can happen but let’s recap with an example.

class HomeController : Controller
{
    public ActionResult Index() 
    {
            
        doWorkAsync().Wait();
        return View();
    }

    private async Task doWorkAsync() 
    {
        await Task.Delay(500);
    }
}


The above code has an ASP.NET MVC 4 asynchronous action method (I am using .NET 4.5 here) which consumes the private doWorkAsync method. I used ASP.NET MVC here but everything applies for ASP.NET Web API asynchronous action methods as well. Inside the doWorkAsync method, we used Delay method of Task to demonstrate but this could be any method which returns a Task or Task<T>. inside the Index action method, we invoke the Wait method on the task which we got from doWorkAsync method to ensure that we won’t go further unless the operation completes and the interesting part happens right here. At that point we block the UI thread at the same time. When eventually the Task.Delay method completes in the threadpool, it is going to invoke the continuation to post back to the UI thread because SynchronizationContext.Current is available and captured. But there is a problem here: the UI thread is blocked. Say hello to our deadlock!
When you run the application, you will see that the web page will never come back. Solution to this problem is so simple: don’t use the Wait method. The code you should be writing should be as follows:
class HomeController : Controller 
{

   public async Task<ActionResult> Index() 
   {
      await doWorkAsync();
      return View();
   }

   private async Task doWorkAsync() 
   {
      var task = Task.Delay(500);
   }
}


But if you have to use it for some weird reasons, there is another method named ConfigureAwait on Task which you can configure not to use the captured context.

class HomeController : Controller 
{

   public ActionResult Index() 
   {
      doWorkAsync().Wait();
      return View();
   }

    private async Task doWorkAsync() 
   {
      var task = Task.Delay(500);
      await task.ConfigureAwait(continueOnCapturedContext: false);
   }
}

Very nice little and tricky information but a lifesaver.


6 comments:

  1. Dynode Software is one of the best Software Development Company in Bihar. Company also offers Domain Registration, Web Hosting, Web Designer in Patna. We are an award-winning Software Company in Bihar India we offer web design, software development, mobile apps and SEO services. Contact Now!

    ReplyDelete
  2. Content 2
    Get the best digital marketing company in Patna for professional search engine optimization (SEO) services for your company. Dynode Software is that the best choice for you…!! DST is the Top Rated digital marketing company in Patna. Our Agency offers affordable & the best digital marketing services that boost the website's clicks, quality organic traffic, inquiries, and sales. Call Now to improve the online visibility of your website

    ReplyDelete
  3. Dynode Software is an IT Consultancy and Outsourcing company headquartered in Patna. Our mission is to deliver end to end IT Solutions across the globe by leveraging through latest technologies and bringing a positive social change. Approach Dynode Software best software company Bihar..

    ReplyDelete
  4. Dynode Software is a rapidly growing leader among website development agency in Patna , Bihar. In the current scenario. If you are looking for Best website development agency in Patna approach us

    ReplyDelete
  5. Hire the mobile app development services of Dynode Software and get the hybrid app for your business. The Software Company in Bihar offers hybrid software solutions for businesses of all sorts. You can get a customized app for your business at an affordable cost.

    ReplyDelete
  6. Dynode Software helps you to deliver prompt and accurate SEO services and save great operational time. The software developed by the software development company is highly flexible and can be integrated well with other key components as well. Contact us for video marketing in patna .

    ReplyDelete