我试图弄清楚如何在我的Asp.Net MVC中使用C#中的async / await。 主要的一点似乎是它帮助asp.net在你做IO时从工作池中释放线程(所以他们可以处理其他东西)。为此,您必须从执行IO调用的方法到控制器操作提升async / await修饰符(最好只有几层)。
在没有将async / await提升到我的控制器的情况下使用此功能有什么意义吗? (例如,在调用Async方法后添加Task.Wait。)
答案 0 :(得分:2)
答案是“是”,但在动作中使用Task.Wait()
并不是一个好主意,因为它可能导致死锁情况。
请参考指南中的以下内容,Async/Await Best Practice 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 ;如果将“ConfigureAwait(false)
”添加到DelayAsync
中的代码行,则可以避免死锁。这次,当await完成时,它会尝试在线程池上下文中执行async方法的其余部分。该方法能够完成,完成其返回的任务,并且没有死锁。如果您需要逐渐将应用程序从同步转换为异步,则此技术特别有用。
答案 1 :(得分:0)
不要使用Task.Wait,因为它可能会死锁或产生AggregateException。如果您需要这样做,那么您应该使用非阻塞的Task.WhenAll。
但一般来说,最安全的是端到端使用异步代码。在整个堆栈中使用异步的好处是,您的代码将更容易调试,错误处理更加简单。
所以是,如果你打算使用async / await - 将它包含在你的控制器中并避免使用像Task.Wait这样的阻塞代码。