【问题标题】:What is the advantage of using async with MVC5?将异步与 MVC5 一起使用有什么好处?
【发布时间】:2017-12-22 15:24:24
【问题描述】:

有什么区别:

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 中使用异步并没有什么好处,但是也有很多负面影响
  • @ChrisMarisic - 最严重的问题之一:您不能使用 ReaderWriterLock 或任何其他同步原语(Semaphore 除外)。

标签: asp.net-mvc task-parallel-library async-await asp.net-mvc-5 asp.net-identity


【解决方案1】:

只有在执行 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 中的异步,2012,Alex Davies)
  • @Darin 为什么释放主线程如此重要?线程有限吗?
  • @Omtechguy 更好的解决方案是将非 ASP.NET 请求移动到 CDN。一个简单的 CDN 只是使用子域和单独的应用程序池来存储 javascript 和图像等物理文件。或者,您可以使用 NgineX / Lighttpd / Apache 来存储文件,或者您可以使用第三方服务,例如 Akamai(CDN 之王,但最昂贵)
  • 我还是一头雾水。当调用CheckPasswordAndSignInAsync 时,ASP.NET 从线程池中获取另一个线程并开始执行它,不是吗?如果没有,checking password procedure 在哪里执行?
【解决方案2】:

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

是否会产生一些新任务,是否应该等待它。始终考虑那些 70 毫秒,大约是 70 毫秒。最大。任何方法调用都应该花费的时间。如果它更长,那么您的 UI 很可能不会感觉非常灵敏。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 如果您的 aspnet 应用程序主要由对其他 Web 服务器的调用组成,那么您在很大程度上表现为“网关”/“代理”,并且异步对此很有用。
    猜你喜欢
    • 2014-01-18
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    • 2019-05-02
    • 2020-11-05
    • 1970-01-01
    相关资源
    最近更新 更多