First time here? You are looking at the most recent posts. You may also want to check out older archives or the tag cloud. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS. Thank you for visiting! (hide this)

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.

posted on Wednesday, December 7, 2011 7:06 PM

Comments on this entry:

# re: Set the AsyncTimeout attribute for your async controllers

Left by Daniel Lidström at 12/8/2011 1:58 PM

Are you making your users wait for 45 seconds plus while the request is being processed?

# re: Set the AsyncTimeout attribute for your async controllers

Left by Simone Chiaretta at 12/8/2011 2:14 PM

yes, the user will wait till the processing is complete.
Async controllers are asynchronous only on the server...
Probably the best solution would be to fire the task with an ajax request, and then have the page polling for the completion of the task and update the screen accordingly.
But that's much more than just having an Async action.
Async actions are meant to be used to free up thread on the server while the execution is done on another thread outside of the pool handled by the webserver.

Comments have been closed on this topic.