Asp.net mvc 4 如何使ASP.NET MVC控制器方法异步

Asp.net mvc 4 如何使ASP.NET MVC控制器方法异步,asp.net-mvc-4,task-parallel-library,Asp.net Mvc 4,Task Parallel Library,我正在对各种MVC控制器启动多个ajax调用,以加载页面的不同部分。然而,当这到达控制器时,似乎一次只运行一个。我猜这是因为默认情况下ASP.NETMVC控制器是同步的?我还测试了在两个浏览器选项卡上加载页面,第二个选项卡总是等待第一个 为了解决这个问题,我尝试使讨论中的控制器方法异步。我做了以下几点来做到这一点 将异步附加到控制器方法名称 使控制器方法返回异步任务 使用Task.Factory.StartNew方法在单独的线程中完成方法中的工作主体 例如,现在讨论的控制器方法如下所示

我正在对各种MVC控制器启动多个ajax调用,以加载页面的不同部分。然而,当这到达控制器时,似乎一次只运行一个。我猜这是因为默认情况下ASP.NETMVC控制器是同步的?我还测试了在两个浏览器选项卡上加载页面,第二个选项卡总是等待第一个

为了解决这个问题,我尝试使讨论中的控制器方法异步。我做了以下几点来做到这一点

  • 将异步附加到控制器方法名称
  • 使控制器方法返回异步任务
  • 使用Task.Factory.StartNew方法在单独的线程中完成方法中的工作主体
  • 例如,现在讨论的控制器方法如下所示

        public async Task<JsonResult> GetUser(int userId)
        {
            var result = await Task.Factory.StartNew(() => Task.Run(() =>
            {                
                return userService.GetUser(userId);
            })).Result;
            return new JsonResult()
            {
                Data = result,
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        } 
    
    公共异步任务GetUser(int userId) { var result=wait Task.Factory.StartNew(()=>Task.Run(()=> { 返回userService.GetUser(userId); })).结果; 返回新的JsonResult() { 数据=结果, JsonRequestBehavior=JsonRequestBehavior.AllowGet }; }
    然而,它似乎仍然是同步的。我是错过了什么,还是完全走错了方向?我没有太多地使用任务库,因此可能遗漏了一些重要的内容?

    不,您的假设很可能是错误的。您的问题可能是两个问题中的一个(或两个)

    首先,大多数web浏览器都有请求限制,一次只允许向同一服务器发出一定数量的请求

    其次,您可能遇到了会话对象的限制,导致使用会话的多个请求被序列化,因为会话本身不是多线程的

    简单的回答是,如果在操作方法中不使用会话,只需将其添加到方法中即可

    [SessionState(SessionStateBehavior.Disabled)]
    public class AjaxTestController : Controller
    {        
        //...As above
    }
    
    如果您只需要阅读会话,请执行以下操作:

    [SessionState(SessionStateBehavior.ReadOnly)]
    public class AjaxTestController : Controller
    {        
        //...As above
    }
    

    但是,对于浏览器的限制,您无能为力,因为不同的浏览器有特定的请求限制。这些可以通过注册表(或浏览器配置)项(通常)进行更改,但在大多数情况下,您不能强制用户这样做。

    mvc控制器本质上是异步的,您如何确定它是同步的?唯一的原因可能是在userService中实现了一些锁


    您可以尝试使用jquery对web服务进行数百次ajax调用,MVC4.0中引入的一个重要特性是异步控制器,它支持编写异步操作方法。异步控制器允许在不使工作线程空闲的情况下执行操作

    调用异步操作时,将执行以下步骤:

    Web服务器从线程池(工作线程)获取一个线程,并安排它处理传入的请求。此工作线程启动异步操作。工作线程返回到线程池以服务另一个Web请求。异步操作完成后,将通知ASP.NET。Web服务器从线程池(可能是启动异步操作的线程的不同线程)获取工作线程,以处理请求的其余部分,包括呈现响应

    将同步操作方法转换为异步操作方法

    下面是同步操作方法及其异步等效版本的示例

    同步控制器:

    public class TestController : Controller
     {
       public ActionResult Index()
        {
         return View(); 
        }
     }
    
    上述操作的异步变体:

    public class TestController : AsyncController
    {
       public void IndexAsync()
       {
        return View();
       }
    
      public ActionResult IndexCompleted()
      {
       return View();
      }
    }
    
    步骤:

    • 同步控制器是从控制器派生的类 类来实现AsyncController,而不是派生 控制器,从AsyncController类派生它。 从AsyncController派生的控制器使ASP.NET能够 处理异步请求,它们仍然可以为同步请求提供服务 行动方法

    • 对应于同步中的同步动作方法 您需要为中的操作创建两个方法 异步控制器。启动异步控制器的第一个方法 进程的名称必须由操作和后缀组成 “异步”。异步调用时调用的另一个方法 进程完成(回调方法)的名称必须包含 操作和后缀“已完成”

    在上面的示例中,索引操作已转换为异步控制器中的两种方法:IndexAsync和IndexCompleted

    IndexAsync方法返回void,而IndexCompleted方法返回ActionResult实例。尽管该操作由两个方法组成,但使用与同步操作方法(例如,控制器/索引)相同的URL访问它

    请注意以下有关异步操作方法的信息:

  • 如果操作名称是Sample,那么框架将查找 SampleSync和SampleCompleted方法

  • 视图页面应命名为Sample.aspx,而不是samplesync.aspx 或SampleCompleted.aspx。(操作名称是Sample,而不是Sample Samync)

  • 控制器不能包含名为SampleSync的异步方法 以及一个名为Sample的同步方法。如果是的话 由于SampleSync action方法和Sample action方法具有相同的请求 签名


  • 有关更多详细信息,请单击此处:

    将会话设置为禁用或只读会解决此问题。在我找到的异步控制器示例中,没有看到任何提到这一点的内容。谢谢lot@Gavin-这是因为问题与异步无关。异步用于获得更好的资源可伸缩性。这个问题是特定于会话的。@Gavin-顺便说一句,这是XY问题的一个经典示例。-您有问题,您的请求正在序列化