异步控制器通过 jQuery 阻止 ASP.NET MVC 中的请求

IT技术 c# javascript asp.net-mvc-2 jquery
2021-03-18 19:39:05

我刚刚开始在我的项目中使用 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("...");
    }
}

但是我发现,当我使用 jQuery ajax 请求调用 LongRunningAction 时,我在此之后发出的任何进一步请求都会备份到它的后面,并且在 LongRunningAction 完成之前不会被处理。例如,调用耗时 10 秒的 LongRunningAction,然后调用不到一秒的 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个回答

这里有两个问题。首先是你的控制器不是真正的异步。启动一个 ThreadPool 线程来执行工作通常比仅仅从 action 方法本身做所有事情具有更糟糕的性能特征,因为您仍然从 ASP.NET(它只共享 CLR ThreadPool)获取 ThreadPool 资源,您现在强制 CLR 和操作系统处理线程。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ee728598.aspx#choosing_synchronous_or_asynchronous_action_methods基本上,该链接归结为如果您不能将 I/O 完成端口用于异步操作,您就不太可能看到性能提高。

第二个问题是 ASP.NET MVC 对所有请求都使用会话锁。单个 Session 中的多个请求将始终被序列化,否则如果一个控制器在另一个控制器试图读取它时写入 Session,则用户的 Session 可能会损坏。有关上下文和解决方法,请参阅http://forums.asp.net/t/1501623.aspxMVC 2 Futures 有一种禁用此锁的方法;它也可能包含在 MVC 3 中。有关更多信息,请参阅https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx

使用 async 和 await 仍然如此吗?
2021-05-21 19:39:05

Acutally 问题在于 this.HttpContext.Session,因为它被锁定,如果您在 AsyncController 中向会话写入任何内容,您应该避免它并使用 this.HttpContext.Application - 这将解决问题,我有同样的问题,试试我们

这是错误的。HttpContext.Application Enables sharing of global information across multiple sessions and requests within an ASP.NET application.这与 Session 不同。
2021-05-10 19:39:05
Erik Philips - 我写的没有错。当前会话被初始的第一个 thread.request 锁定,因此它被锁定在该线程中,在异步回调中,他正在并行发出其他请求,因此他需要在应用程序级别使用共享会话。
2021-05-15 19:39:05