在MVC5中使用异步的优势是什么?


120

之间有什么区别?

public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = IdentityManager.Authentication.CheckPasswordAndSignIn(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
        if (result.Success)
        {
            return Redirect("~/home");
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}

和:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = await IdentityManager.Authentication.CheckPasswordAndSignInAsync(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
        if (result.Success)
        {
            return Redirect("~/home");
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}

我看到MVC代码现在具有异步功能了,但有什么区别。一个是否比另一个具有更好的性能?用一个问题调试比另一个问题容易吗?我应该为我的应用程序更改其他控制器以添加Async吗?


在绝大多数情况下,在MVC中使用异步并没有带来什么好处,但是存在很多负面影响
Chris Marisic

1
@ChrisMarisic-最严重的问题之一:您不能使用ReaderWriterLock或任何其他同步原语(信号量除外)。
Quarkly '18

Answers:


170

仅当您执行I / O绑定的操作(例如远程服务器调用)时,异步操作才有用。异步调用的好处是在I / O操作期间,没有使用ASP.NET工作线程。因此,这是第一个示例的工作方式:

  1. 当请求执行该操作时,ASP.NET从线程池中获取一个线程并开始执行它。
  2. IdentityManager.Authentication.CheckPasswordAndSignIn方法被调用。这是一个阻塞调用->在整个调用过程中,工作线程受到威胁。

这是第二个呼叫的工作方式:

  1. 当请求执行该操作时,ASP.NET从线程池中获取一个线程并开始执行它。
  2. IdentityManager.Authentication.CheckPasswordAndSignInAsync被称为其立即返回。注册一个I / O完成端口,并将ASP.NET辅助线程释放到线程池。
  3. 稍后,当操作完成时,将向I / O完成端口发出信号,从线程池中提取另一个线程以完成返回视图的操作。

如您在第二种情况下所见,ASP.NET工作线程仅在短时间内使用。这意味着池中有更多线程可用于处理其他请求。

综上所述,仅当您拥有真正的异步API时,才使用异步操作。如果您在异步操作中进行阻止调用,那么您将失去它的全部好处。


如何进行上下文同步。这不是您根本不想使用异步操作的开销吗?“实际上异步执行的异步方法的开销完全取决于它是否需要使用SynchronizationContext.Post切换线程。如果确实如此,开销将由它在恢复时执行的线程切换控制。这意味着当前的SynchronizationContext使有很大的不同。” (C#5.0中的Async,2012年,Alex Davies)
annemartijn 2014年

1
@Darin为什么释放主线程如此重要?线程受限吗?
Omtechguy 2014年

1
@Omtechguy更好的解决方案是将非ASP.NET请求移至CDN。一个简单的CDN仅使用子域和单独的应用程序池来存储诸如javascript和图像之类的物理文件。或者,您可以使用NgineX / Lighttpd / Apache来存储文件,也可以使用第三方服务,例如Akamai(CDN的王者,但价格最昂贵)
Chris Marisic,2016年

我还是很困惑。当CheckPasswordAndSignInAsync被调用时,ASP.NET需要从线程池的另一个线程并开始执行它,不是吗?如果没有,在哪里checking password procedure执行?
KevinBui

2

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

是否是将要产生的某些新任务,以及是否应该等待它。始终考虑一下这70毫秒,大约是30毫秒。最大 任何方法调用应花费的时间。如果更长,那么您的用户界面很可能不会具有很好的响应能力。


0

在启动时看到大量并发请求或负载突增(并发性突然增加)的Web应用程序中,使这些Web Service调用异步可以提高应用程序的响应速度。异步请求所花的时间与同步请求所花的时间相同。例如,如果一个请求进行的Web服务调用需要两秒钟才能完成,那么无论是同步还是异步执行,该请求都将花费两秒钟。但是,在异步调用期间,在等待第一个请求完成时,不会阻止线程响应其他请求。因此,当有许多并发请求调用长时间运行的操作时,异步请求会阻止请求排队和线程池增长。


如果您的aspnet应用程序主要由对其他Web服务器的调用组成,则您的行为很大程度上就相当于“网关” /“代理”,异步对于此目的很有用。
克里斯·马里西奇
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.