Асинхронный контроллер блокирует запросы в ASP.NET MVC через jQuery - PullRequest
24 голосов
/ 28 мая 2010

Я только начал использовать AsyncController в своем проекте, чтобы позаботиться о некоторых длительных отчетах. Это казалось идеальным в то время, когда я мог запустить отчет и затем выполнить несколько других действий, ожидая его возвращения и заполнения элементов на экране.

Мой контроллер выглядит примерно так. Я попытался использовать поток для выполнения длинной задачи, которая, как я надеялся, освободила бы контроллер для принятия большего количества запросов:

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("...");
    }
}

Но я обнаружил, что когда я вызываю LongRunningAction с помощью jjuery ajax-запроса, любые последующие запросы, которые я делаю после этого, сохраняются за ним и не обрабатываются до тех пор, пока LongRunningAction не завершится. Например, вызовите LongRunningAction, который занимает 10 секунд, а затем вызовите AnotherControllerAction, который меньше секунды. AnotherControllerAction просто ждет, пока LongRunningAction завершит свою работу, прежде чем вернуть результат.

Я также проверил код jQuery, но это все равно происходит, если я специально установил «async: true»:

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

В данный момент я просто должен предположить, что я использую это неправильно, но я надеюсь, что один из вас, ребята, сможет очистить мой умственный блок!

Ответы [ 2 ]

31 голосов
/ 28 мая 2010

Здесь есть две проблемы. Во-первых, ваш контроллер не является действительно асинхронным. Вращение потока ThreadPool для выполнения работы обычно имеет худшие характеристики производительности, чем простое выполнение всего из самого метода действия, поскольку вы все еще берете ресурсы ThreadPool из ASP.NET (который просто разделяет CLR ThreadPool) , и теперь вы заставляете CLR и ОС манипулировать потоками. См. http://msdn.microsoft.com/en-us/library/ee728598.aspx#choosing_synchronous_or_asynchronous_action_methods для получения дополнительной информации. По сути, эта ссылка сводится к тому, что если вы не можете использовать порты завершения ввода / вывода для асинхронных операций, вы вряд ли увидите улучшение производительности.

Вторая проблема заключается в том, что ASP.NET MVC принимает блокировку сеанса для всех запросов. Несколько запросов в пределах одного сеанса всегда будут сериализованы, так как в противном случае сеанс пользователя может быть поврежден, если один контроллер записывает в сеанс, когда другой контроллер пытается его прочитать. См. http://forums.asp.net/t/1501623.aspx для контекста и обходного пути. MVC 2 Futures имеет способ отключить эту блокировку; это может также быть включено в собственно MVC 3. Для получения дополнительной информации см. https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx.

4 голосов
/ 18 июля 2011

На самом деле проблема заключается в этом. HTTConContext.Session, потому что он заблокирован, если вы записываете что-либо в сеанс в AsyncController, вы должны избегать этого и использовать this.HttpContext.Application - это решит проблему У меня была такая же проблема, и попробуйте нас

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...