如何防止使用异步的asp.net应用程序死锁
本文关键字:asp net 应用程序 死锁 异步 何防止 | 更新日期: 2023-09-27 18:08:56
考虑一个使用异步方式编写的asp.net MVC应用程序。碰巧在顶层和底层使用异步,有一些间隙(例如result调用),这会导致死锁。
我听说.ConfigureAwait(false)
可能有帮助,但我不确定如何。所以问题是:如何使用.ConfigureAwait(false)
来防止死锁?
这个应用程序有一个类将表示层与业务逻辑分开。我想让所有的业务逻辑方法返回任务与.ConfigureAwait(false)
。这样对/够吗?
使用ConfigureAwait(false)
是一种变通方法,而不是最终的解决方案。你可能会消除由task.Result
引起的死锁,但你仍然会阻塞请求线程,有效地扼杀了在服务器端使用async/await
的主要优势,这提高了web应用程序的可伸缩性。
另一个不太明显的问题是,await task.ConfigureAwait(false)
之后的延续代码将失去对AspNetSynchronizationContext
提供的HTTP请求的环境信息的访问权(例如,不再有HttpContext.Current.Items
)。
理想情况下,你应该重构你的服务/数据层来处理任务,并使用async/await
"一直向下"到根方法,这是一个异步控制器方法。这并不难,只需使用Task<T>
而不是T
作为数据访问接口:
public interface IAsyncData
{
Task<int> AsyncData { get; }
}
不是public interface IData
{
int Data { get; }
}
然后在实现数据存储库时使用异步Task-based
数据访问api,并在实现MVC控制器时使用data.Data
时使用await data.AsyncData
。
您可以通过在现有的同步数据访问层中使用Task.FromResult
代替AsyncData
来逐步完成这种转换。