如何防止使用异步的asp.net应用程序死锁

本文关键字:asp net 应用程序 死锁 异步 何防止 | 更新日期: 2023-09-27 18:08:56

考虑一个使用异步方式编写的asp.net MVC应用程序。碰巧在顶层和底层使用异步,有一些间隙(例如result调用),这会导致死锁。

我听说.ConfigureAwait(false)可能有帮助,但我不确定如何。所以问题是:如何使用.ConfigureAwait(false)来防止死锁?

这个应用程序有一个类将表示层与业务逻辑分开。我想让所有的业务逻辑方法返回任务与.ConfigureAwait(false)。这样对/够吗?

如何防止使用异步的asp.net应用程序死锁

使用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来逐步完成这种转换。