【问题标题】:Why do you use async if you don't promote it to the controller?如果不将异步提升到控制器,为什么还要使用它?
【发布时间】:2017-03-24 17:07:42
【问题描述】:

我试图弄清楚如何在我的 Asp.Net MVC 中使用 C# 中的 async/await。 要点似乎是它有助于 asp.net 在您进行 IO 时从工作池中释放线程(以便它们可以处理其他东西)。为此,您必须将执行 IO 调用的方法中的 async/await 修饰符提升到控制器操作(最好只有几层)。

在不将异步/等待提升到我的控制器的情况下使用此功能有什么意义吗? (例如,通过在调用 Async 方法后添加 Task.Wait)。

【问题讨论】:

  • 如果您也基本上手动执行主机系统为异步代码执行的相同操作,即在等待时执行其他任务,则它可能会有所帮助。这可能相当复杂,但可行。异步真的没有什么魔力,它主要是一种允许顶级消费代码做其他事情而底层基础设施代码等待完成的方法。主机系统在顶层支持它,但您的代码也可以。但是,如果您只是简单地将异步操作“掩盖”在同步操作之后,那么您实际上就是在否定这种好处。

标签: asp.net-mvc async-await


【解决方案1】:

答案是“是”,但在操作中使用Task.Wait() 不是一个好主意,因为它可能导致死锁情况。

请考虑指南中的以下内容,Async/Await Best Practice by Stephen Cleary

图 3 阻塞异步代码时的常见死锁问题

public static class DeadlockDemo
{
   private static async Task DelayAsync()
   {
      await Task.Delay(1000);
   }
   // This method causes a deadlock when called in a GUI or ASP.NET context.
   public static void Test()
   {
       // Start the delay.
       var delayTask = DelayAsync();
       // Wait for the delay to complete.
       delayTask.Wait();
   }
}

但是,如果您像这样将ConfigureAwait(false) 添加到DelayAsync()

await Task.Delay(1000).ConfigureAwait(false)

那么您可以避免死锁,如文章中所述:

除了性能,ConfigureAwait 还有一个重要的方面:它可以避免死锁。再次考虑图 3;如果在DelayAsync 的代码行中添加“ConfigureAwait(false)”,则可以避免死锁。这一次,当等待完成时,它会尝试在线程池上下文中执行剩余的异步方法。该方法能够完成,它完成了它返回的任务,并且没有死锁。如果您需要逐渐将应用程序从同步转换为异步,此技术特别有用。

【讨论】:

  • 如果我理解得很好,我的问题的答案是“你必须推广它”对吗?因为死锁问题
  • 绝对是的:)
【解决方案2】:

不要使用 Task.Wait,因为它会死锁或产生 AggregateException。如果您需要这样做,那么您应该使用非阻塞的Task.WhenAll

一般来说,端到端使用异步代码是最安全的。在整个堆栈中使用异步的好处是您的代码将更容易调试并且错误处理更简单。

所以是的,如果您要使用 async/await - 将其包含在您的控制器中,并避免使用诸如 Task.Wait 之类的阻塞代码。

【讨论】:

    猜你喜欢
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多