ASP.NET MVC中的异步控制器:真正的优势/如何实现?


12

我一直在阅读有关ASP.NET MVC中异步控制器方法的文章(http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx),我认为我可能错过了重点。

考虑一下我写的这种方法,它与文章中的示例非常相似:

[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    WidgetPageViewModel model = new WidgetPageViewModel()
    {
        toAdd = new Widget()
    };
    model.all = await _repo.GetAllAsync(cancellationToken);
    return View(model);
}

据我了解,这是运行时事物将如何展开的方式:

  1. 将为传入的HTTP请求创建一个ASP.NET线程。

  2. 该线程将(已经完成了一些必要的初步工作)输入上述我的Index()方法。

  3. 执行将到达“ await”关键字,并在另一个线程上启动数据获取过程。

  4. 原始的“ ASP.NET”线程将返回调用我的处理程序方法的代码,并将Task类的实例作为返回值。

  5. 调用我的处理程序方法的基础结构代码将继续在原始的“ ASP.NET”线程上运行,直到达到需要使用实际ActionResult对象(例如,呈现页面)的程度。

  6. 然后,调用者将使用Task.Result成员访问此对象,这将使它(即“ ASP.NET”线程)等待上述步骤3中隐式创建的线程。

与没有等待/异步的同一件事相比,我看不到这完成了什么,除了我认为是琐碎的两件事:

  • 由await创建的调用者线程和工作线程可以并行运行一段时间(上述#5的“直到”部分)。我的预感是这段时间很小。当基础结构调用控制器方法时,我认为它通常需要控制器调用的实际ActionResult才能做更多(如果有的话)。

  • 有一些有用的新基础结构与超时和取消长时间运行的异步控制器操作有关。

添加异步控制器方法的目的应该是释放那些ASP.NET辅助线程以实际响应HTTP请求。这些线程是有限的资源。不幸的是,我没有看到文章中建议的模式实际上如何用于保存这些线程。即使这样做,并且以某种方式将处理请求的负担转移到了一些非ASP.NET线程上,那又完成了什么呢?碰巧能够处理HTTP请求的线程与一般线程有很大不同吗?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread - 不必要。 async不需要另一个线程...这是一个延续。可以通过在同一线程上对
罗伯特·哈维


“执行将到达await关键字,并在另一个线程上启动数据获取过程。” 您会倒退:等待是在回来的时候。尝试将其拆分,以便将GetAllAsync()的结果保存在变量中,然后等待它,看看它是否变得更加清晰。
Esben Skov Pedersen

Answers:


9

不使用任务并行库(TPL)的ASP.Net受线程池中的线程数限制,它可以同时处理的请求数。使用TPL的ASP.Net受到计算机处理请求的CPU /内存/ IO的限制。

任务并行库(TPL)不会像您认为的那样消耗线程。任务不是线程,它们是某些计算单元的包装。任务计划程序负责在不繁忙的任何线程上执行每个任务。在运行时,等待任务不会阻塞线程,它只是驻留执行状态,以便它可以在以后的时间继续执行。

通常,单个HTTP请求将由单个线程处理,从池中完全删除该线程,直到返回响应。使用TPL,您不受此约束的约束。传入的任何请求都会以计算所需的每个计算单位开始继续,以计算能够在池中的任何线程上执行的响应。使用此模型,与标准ASP.Net相比,您可以处理更多的并发请求。


那么什么时候ASP.NET线程返回到池中?什么时候打了“ await”关键字?
user1172763

async / await + TPL允许编译器将您的代码分为独立的计算单元,这些任务由任务调度程序执行。当任务计划程序没有更多可以执行的任务并且线程完成分配给它的工作时,线程将从概念上返回到池中。
mortalapeman

从概念上讲这是正确的,可能是一个有用的答案...但是由于线程敏捷性,实际情况稍微复杂了一点。
John Wu,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.