Today I decided to convert an action that was making various long calls to external webservices to be asynchronous. With the synchronous version it was long but still under the default script timeout of ASP.NET, so I was very surprised when the async version was returning a System.TimeoutException, even if it was still taking the same amount of time. I tried increasing the ScriptTimeout, but still no luck: the page was timing out.

After a bit of searching online I found out that for some strange reason, async controllers have a different timeout, specified by the Timeout property of the AsyncManager; and by default this value is 45 seconds.

Instead of manually setting this value in your action, you can use two action attributes so that infrastructural code doesn’t interfere with your actions’ code:

  • AsyncTimeoutAttribute – you can set the timeout of the async action. It is specified in milliseconds: 10 minutes is 600000.
  • NoAsyncTimeoutAttribute – if you want to set the timeout to indefinte (ie the action will run forever)

Here following a very simple example of an Async controller with the AsyncTimeout attribute set to 10 minutes.

public class SyncController : AsyncController
{
    [AsyncTimeout(600000)]
    public void SyncAllAsync()
    {
        syncManager.OutstandingOperations.Increment();
        var bg = new BackgroundWorker();
        bg.DoWork += (o, e) => DoStuff("Some other stuff", e);
        bg.RunWorkerCompleted += (o, e) =>
                 {
                     AsyncManager.Parameters["model"] = e.Result;
                     AsyncManager.OutstandingOperations.Decrement();
                 };
        bg.RunWorkerAsync();
    }
    
    public ActionResult SyncAllCompleted(SyncViewModel model)
    {
        return View(model);
    }
    
    private void DoStuff(string input, DoWorkEventArgs e)
    {
        SyncViewModel model = new SyncViewModel();
        Thread.Sleep(60000);
        model.Text=input;
        e.Result = model;
    }
}

The code doesn’t do a lot, just fires up the background worker and calls the DoStuff method asynchronously. I just realize I could have also probably used the TPL and the Task with continuation… maybe I’ll write an update to this blog in the next days while I work on my project and need to process more “stuff” in parallel.