Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

c# - Asynchronous Controller is blocking requests in ASP.NET MVC through jQuery

I have just started using the AsyncController in my project to take care of some long-running reports. Seemed ideal at the time since I could kick off the report and then perform a few other actions while waiting for it to come back and populate elements on the screen.

My controller looks a bit like this. I tried to use a thread to perform the long task which I'd hoped would free up the controller to take more requests:

public class ReportsController : AsyncController
{
    public void LongRunningActionAsync()
    {
        AsyncManager.OutstandingOperations.Increment();

        var newThread = new Thread(LongTask);
        newThread.Start();
    }

    private void LongTask()
    {
        // Do something that takes a really long time
        //.......

        AsyncManager.OutstandingOperations.Decrement();
    }

    public ActionResult LongRunningActionCompleted(string message)
    {
        // Set some data up on the view or something...

        return View();
    }

    public JsonResult AnotherControllerAction()
    {
        // Do a quick task...

        return Json("...");
    }
}

But what I am finding is that when I call LongRunningAction using the jQuery ajax request, any further requests I make after that back up behind it and are not processed until LongRunningAction completes. For example, call LongRunningAction which takes 10 seconds and then call AnotherControllerAction which is less than a second. AnotherControllerAction simply waits until LongRunningAction completes before returning a result.

I've also checked the jQuery code, but this still happens if I specifically set "async: true":

$.ajax({
    async: true,
    type: "POST",
    url: "/Reports.aspx/LongRunningAction",
    dataType: "html",
    success: function(data, textStatus, XMLHttpRequest) { 
           // ...
        },
    error: function(XMLHttpRequest, textStatus, errorThrown) { 
       // ...
    }
});

At the moment I just have to assume that I'm using it incorrectly, but I'm hoping one of you guys can clear my mental block!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are two issues in play here. The first is that your controller is not truly asynchronous. Spinning up a ThreadPool thread to perform work generally has worse performance characteristics than just doing everything from within the action method itself, as you're still taking ThreadPool resources from ASP.NET (which just shares the CLR ThreadPool), and you're now forcing the CLR and the OS to juggle threads. See http://msdn.microsoft.com/en-us/library/ee728598.aspx#choosing_synchronous_or_asynchronous_action_methods for more information. Basically, what that link boils down to is that if you can't use I/O completion ports for your asynchronous operations, you're very unlikely to see improved performance.

The second issue is that ASP.NET MVC takes a Session lock on all requests. Multiple requests within a single Session will always be serialized, as otherwise the user's Session could become corrupted if one controller writes to Session as another controller is trying to read it. See http://forums.asp.net/t/1501623.aspx for context and a workaround. MVC 2 Futures has a way of disabling this lock; it may also be included in MVC 3 proper. See https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx for more information on this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...