【问题标题】:Asynchronous Controller is blocking requests in ASP.NET MVC through jQuery异步控制器通过 jQuery 阻塞 ASP.NET MVC 中的请求
【发布时间】:2011-02-25 01:03:30
【问题描述】:

我刚刚开始在我的项目中使用 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 完成之前不会被处理。例如,调用 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) { 
       // ...
    }
});

目前我只能假设我用错了,但我希望你们中的一个人能清除我的心理障碍!

【问题讨论】:

  • 您是在 IIS 还是 WebDev 上执行此操作?嗯,WebDev 与 IIS 相比,是“不那么激进的多线程”。
  • 我也有同样的问题,请问你是怎么解决的?

标签: c# javascript asp.net-mvc-2 jquery


【解决方案1】:

这里有两个问题。首先是您的控制器不是真正的异步。启动 ThreadPool 线程来执行工作通常具有更糟糕的性能特征,而不是仅仅从操作方法本身执行所有操作,因为您仍然从 ASP.NET 获取 ThreadPool 资源(它只共享 CLR 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.aspx。 MVC 2 Futures 有一种禁用此锁的方法;它也可能包含在 MVC 3 中。有关这方面的更多信息,请参阅https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx

【讨论】:

  • 使用 async 和 await 仍然如此吗?
【解决方案2】:

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

【讨论】:

  • 这是错误的。 HttpContext.ApplicationEnables sharing of global information across multiple sessions and requests within an ASP.NET application.。这和 Session 不一样。
  • Erik Philips - 我写的没有错。当前会话被初始第一个线程请求锁定,因此它被锁定在该线程中,在异步回调中他正在并行发出其他请求,因此他需要在应用程序级别使用共享会话。
猜你喜欢
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
  • 2012-10-29
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
相关资源
最近更新 更多