Search code examples
asp.net-mvc-4asynchronousactionresultasync-awaitasynccontroller

Async ActionResult implementation is blocking


Okay,

Here I have an MVC 4 application and I am trying to create an Asynchronous ActionResult with in that.

Objective : User has a download PDF Icon on the WebPage, and downloading takes much of time. So while server is busy generating the PDF, the user shall be able to perform some actions in webpage.

(clicking "download PDF" link is sending and ajax request to the server, server is fetching some data and is pushing back the PDF)

What is happening is while I call the ajax to download the PDF it starts the process, but blocks every request until and unless it returns back to the browser. That is simple blocking request.

What I have tried so far.

1) Used AsyncController as a base class of controller.

2) Made the ActionResult to an async Task DownloadPDF(), and here I wrapped the whole code/logic to generate PDF into a wrapper. This wrapper is eventually an awaitable thing inside DownloadPDF()

something like this.

public async Task<ActionResult> DownloadPDF()
{
    string filepath = await CreatePDF();
    //create a file stream and return it as ActionResult
}

private async Task<string> CreatePDF()
{
    // creates the PDF and returns the path as a string
    return filePath;
}

YES, the Operations are session based.

Am I missing some thing some where?


Solution

  • Objective : User has a download PDF Icon on the WebPage, and downloading takes much of time. So while server is busy generating the PDF, the user shall be able to perform some actions in webpage.

    async will not do this. As I describe in my MSDN article, async yields to the ASP.NET runtime, not the client browser. This only makes sense; async can't change the HTTP protocol (as I mention on my blog).

    However, though async cannot do this, AJAX can.

    What is happening is while I call the ajax to download the PDF it starts the process, but blocks every request until and unless it returns back to the browser. That is simple blocking request.

    AFAIK, the request code you posted is completely asynchronous. It is returning the thread to the ASP.NET thread pool while the PDF is being created. However, there are several other aspects to concurrent requests. In particular, one common hangup is that by default the ASP.NET session state cannot be shared between multiple requests.

    1) Used AsyncController as a base class of controller.

    This is unnecessary. Modern controllers inspect the return type of their actions to determine whether they are asynchronous.

    YES, the Operations are session based.

    It sounds to me like the ASP.NET session is what is limiting your requests. See Concurrent Requests and Session State. You'll have to either turn it off or make it read-only in order to have concurrent requests within the same session.