ASP.NET MVC 3中的异步 Action 通过两个匹配的方法XxxAsync/XxxCompleted 来定义,这样的异步 Action 只能定义在继承自 AsyncConoller 的类型中。 ASP.NET MVC 4 提供
了一种更加简洁的异步 Action 定义方式,不过为了兼容前一版本,传统的定义方式和AsyncController 类型依然被保留下来。为什么我们需要让 Action 方法异步地执行呢?要回答
这个问题,这就需要了解 ASP.NET 基于线程池 Thread Pool 的请求处理机制。

1. 基于线程池的请求处理机制
ASP.NET 通过线程池的机制处理并发的 HTTP 请求。一个 Web 应用内部维护着一个线程池,当探测到抵达的请求后, ASP.NET 会从池中获取一个空闲的线程来处理它。处理完毕
后,线程不会被回收,而是重新释放到池中。线程池具有一个最大容量,如果创建的线程达到这个上限并且现有的线程均被处于"忙碌"状态,新的 HTTP 请求会被放入一个请求队列
以等待某个线程重新释放到池中。
我们将这些用于处理 HTTP 请求的线程称为工作线程 (Worker Thread) ,而这个线程池自然就叫做工作线程池。

ASP. NET这种基于线程池的请求处理机制主要具有如下两个优势。
  • 工作线程的重用:创建线程的成本虽然不如进程的激活,却也不是一件一蹦而就的事情,
频繁地创建和释放线程会对性能造成极大的损害。线程池机制避免了总是创建新的工作线程来处理每一个请求,被创建的工作线程得到了极大地重用,并最终提高了服务器的吞吐能力。
  • 工作线程数量的限制:资源的有限性决定了服务器处理请求的能力具有一个上限,或者说某台服务器能够处理的请求并发量具有一个临界点,一旦超过这个临界点,整个服务
器将会因不能提供足够的资源而崩溃。由于采用了对工作线程数量具有良好控制的线程池机制, ASP. 并发处理的请求数量不可能超过线程池的最大允许的容量,从而避
免了在高并发情况下工作线程的无限制创建而最终导致整个服务器的崩溃。如果请求处理操作耗时较短,工作线程处理完毕后可以及时地被释放到线程池中以用于
对下一个请求的处理。但是对于比较耗时的操作来说,意味着工作线程将长时间被某个请求独占,如果这样的操作访问比较频繁,在高并发的情况下在线程池中可能找不到空闲的工作
线程用于及时处理最新抵达的请求。如果采用异步的方式来处理这样的耗时请求,工作线程可以让后台线程来接手,而自己可以及时地被释放到线程池中用于进行后续请求的处理,从而提高了整个服务器的吞吐能
力。值得一提的是,异步操作主要用于I1 绑定操作(比如数据库访问和远程服务调用等),而非 CPU 绑定操作,因为异步操作对整体性能的提升来源于当 I/O 设备在处理某个任务的
时候, CPU 可以释放出来去处理另一个任务。如果耗时操作主要依赖于本机 CPU 的运算,用异步方法反而会因为线程调度和线程上下文的切换而影响整体的性能。

2.两种异步 Action 万法的定义

  2.1 XxxAsync/XxxCompleted
  如果使用两个匹配的方法 xxA sync lX xxCompleted 来定义异步 Action ,可以将异步操作实现在 xxA sync 方法中,而将最终内容的响应实现在Xx xCompleted 方法中。 XxxCompleted
可以看成是对 Async 方法的回调,当定义在 xxA sync 方法中的操作以异步方式完成执行后, XxxCompleted 方法会被自动调用。Xx xCompleted 的定义方式和普通的同步 Action
法比较类似。

    public class HomeController : AsyncController
{ //AsyncController
public void ArticleAsync(string name)
{
//ASP.NETMVC 发起异步操作开始 Increment
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew(() =>
{
AsyncManager.Parameters["content"] = "ArticleContent:" + name;
//ASP.NETMVC 发起异步操作结束
AsyncManager.OutstandingOperations.Decrement(); });
Task.Factory.StartNew(() =>
{
AsyncManager.Parameters["content"] = "ArticleContent:" + name;
//ASP.NETMVC 发起异步操作结束 显示操作 AsyndManager.Finish();
AsyncManager.Finish();
}); }
public ActionResult ArticleCompleted(string content)
{
string str = content;
return Content(content);
}
}

  2.2Task 返回值

  如果采用上面的异步 Action 定义方式,意味着我们不得不为一个 Action 定义两个方法,实际上可以通过一个方法来完成对异步 Action 的定义,那就是让 Action 方法返回一个代表
异步操作的 Task 对象。除此之外,以 XxxAsync/XxxCompleted 形式定义的异步 Action 只能出现在继承自 AsyncController 的类型中,而针对 Task 返回值的异步 Action 则对此没有限制。
实际上保留 AsyncController 这个抽象类主要是为了实现对 AS NETMVC 3的向后兼容。

上面通过 XxxAsync /XxxCompleted 形式定义的异步 Action 可以采用如下的定义方式。

  public class HomeController : Controller
{ //Task 返回值
public Task<ActionResult> Article(string name)
{
return Task.Factory.StartNew(() =>
{
AsyncManager.Parameters["content"] = "TaskArticle:" + name;
}).ContinueWith<ActionResult>(task =>
{
string content = (string)AsyncManager.Parameters["content"];
return Content(content);
});
}
}

异步 Action 的定义的更多相关文章

  1. ASP.NET MVC下的异步Action的定义和执行原理

    一.基于线程池的请求处理ASP.NET通过线程池的机制处理并发的HTTP请求.一个Web应用内部维护着一个线程池,当探测到抵达的针对本应用的请求时,会从池中获取一个空闲的线程来处理该请求.当处理完毕, ...

  2. ASP.NET MVC下的异步Action的定义和执行原理[转]

    http://www.cnblogs.com/artech/archive/2012/06/20/async-action-in-mvc.html Visual Studio提供的Controller ...

  3. 夜深了 关于 异步Action的定义的截图

  4. Redux 处理异步 Action

    redux-promise-utils What redux-promise-utils 是一个基于 redux-thunk 和 redux-actions 的工具,符合 FSA 规范,方便开发者处理 ...

  5. redux-amrc:用更少的代码发起异步 action

    很多人说 Redux 代码多,开发效率低.其实 Redux 是可以灵活使用以及拓展的,经过充分定制的 Redux 其实写不了几行代码.今天先介绍一个很好用的 Redux 拓展-- redux-amrc ...

  6. redux学习日志:关于异步action

    当我们在执行某个动作的时候,会直接dispatch(action),此时state会立即更新,但是如果这个动作是个异步的呢,我们要等结果出来了才能知道要更新什么样的state(比如ajax请求),那就 ...

  7. ASP.NET MVC什么时候使用异步Action

    在没有使用异步Action之前,在Action内,比如有如下的写法: public ActionResult Index() CustomerHelper cHelper = new Customer ...

  8. 【React全家桶入门之十三】Redux中间件与异步action

    在上一篇中我们了解到,更新Redux中状态的流程是这种:action -> reducer -> new state. 文中也讲到.action是一个普通的javascript对象.red ...

  9. Redux学习笔记--异步Action和Middleware

    异步Action 之前介绍的都是同步操作,Redux通过分发action处理state,所有的数据流都是同步的,如果需要一步的话怎么办? 最简单的方式就是使用同步的方式来异步,将原来同步时一个acti ...

随机推荐

  1. gen_server的一些心得

    gen_server并不是我原来概念中的tcp_server或者udp_server的概念,只是一个纯粹的消息服务器,另外,附上它的一些回调函数的简单说明参考地址 http://hi.baidu.co ...

  2. SpringCloud子项目

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...

  3. linux 挂载硬盘

    fdisk -l mkfs.ext4 /dev/vdb mkdir /data mount -t ext4 /dev/vdb /data 编辑/etc/fstab /dev/vdb /data ext ...

  4. 使用airmon-ng工具开启监听模式

    使用ifconfig命令查看活动的网络接口 可以看出网卡已经激活了,然后将网卡设置为混杂模式 root@sch01ar:~# airmon-ng start wlan0 用ifconfig查看网卡是否 ...

  5. Flask之数据库操作

    4.2 数据库基本操作 在Flask-SQLAlchemy中,插入.修改.删除操作,均由数据库会话管理.会话用db.session表示.在准备把数据写入数据库前,要先将数据添加到会话中然后调用comm ...

  6. div+css显示两行或三行文字

    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: ; //需要控制的文本行数 overflow: hidd ...

  7. sendMail在centos下的安装

    一.sendEmail介绍   SendEmail is a lightweight, command line SMTP email client. If you have the need to ...

  8. 切面(Aspect)获取请求参数和返回值

    @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 接收到请求, ...

  9. 一篇文章让你了解并掌握memcached

    第一章 memcached简介 1.1为什么引入memcached 随着数据量的增大,访问的集中,REBMS负担加重,数据库响应恶化. Memcached是高性能的分布式内存缓存服务器,目的是通过缓存 ...

  10. Linux&nbsp;2.6.32内核字符设备驱…

    引言:Linux驱动中,字符设备的设计一般会占产品驱动开发的90%以上,作者根据驱动开发的实际经验,总结了一个标准的字符设备驱动的模板,仅供参考. //=======================字 ...