考虑一个使用异步编写的ASP .Net MVC应用程序。在顶层和底层使用异步时会出现一些间隙(例如.Result调用),这会导致死锁。
我听说.ConfigureAwait(false)
可能会帮上忙,但我不确定如何帮上忙。所以问题是:如何使用.ConfigureAwait(false)
来防止死锁?
这个应用程序有一个将表示层与业务逻辑分开的类。我想让所有的业务逻辑方法都用.ConfigureAwait(false)
返回任务。这是否正确/足够了吗?
发布于 2014-06-16 12:29:11
使用ConfigureAwait(false)
与其说是最终解决方案,不如说是一种变通方法。您可能会消除由task.Result
引起的死锁,但您仍然会阻塞请求线程,从而有效地扼杀了在服务器端使用async/await
的主要优势,即提高web应用程序的可扩展性。
另一个不太明显的问题是,await task.ConfigureAwait(false)
之后的延续代码将失去对AspNetSynchronizationContext
提供的环境信息的访问(例如,不再有HttpContext.Current.Items
)。
理想情况下,您应该重构您的服务/数据层以处理任务,并使用async/await
“一直向下”到根方法,这是一个异步控制器方法。这并不难,只需为您的数据访问接口使用Task<T>
而不是T
:
public interface IAsyncData
{
Task<int> AsyncData { get; }
}
而不是
public interface IData
{
int Data { get; }
}
然后在实现数据存储库时使用中的异步MVC数据访问API,并在实现Task-based
控制器时使用await data.AsyncData
。
通过将AsyncData
的Task.FromResult
与现有的同步数据访问层一起使用,您可以逐步完成这种转换。
https://stackoverflow.com/questions/24235812
复制相似问题