前置警告:
我十分清楚在下面所示的上下文中使用.Result是绝对错误的,应该尽一切可能避免。我知道正确的方法是什么。
这个问题的本质更多地与db驱动程序的基础设施有关:Oracle vs Ms-Sql-Server。这在很大程度上是一个学术问题。
System.Web.MVC.dll: ver. 5.2.3.0 (MVC5)
EntityFramework.dll: ver. 6.1.3
EntityFramework.SqlServer.dll: ver. 6.1.3
Oracle.ManagedDataAccess: ver. 4.121.2.0 (oracle driver ver 12.2.0.1.0)
Oracle.ManagedDataAccess.EntityFramework: ver. 6.121.2.0 (oracle driver ver 12.2.0.1.0)
考虑以下存储库及其在ASP.NET MVC控制器中的调用:
考虑以下存储库及其在ASP.NET MVC控制器中的调用:
public class MyRepository {
[...]
public async Task<SomeEntity> GetFirstFooAsync() => await new SomeEFContext().FooTable.FirstOrDefaultAsync();
}
public class SomeController : Controller {
public ActionResult SomeAction() {
var result = new MyRepository.GetFirstFooAsync().Result; //<-- crappy approach I know
[...]
}
}
上述代码片段在底层数据库为Oracle时不会死锁。但是,当使用MS提供的EF关联驱动程序连接到MS-Sql-Server时,这段完全相同的代码会导致死锁。
死锁是此类糟糕代码的预期行为。
- 为什么Oracle驱动程序不会引起死锁?它是否在内部使用了
.ConfigureAwait(false)
或其他调整方式? - 如果Oracle驱动程序确实使用了优化,那么即使适当地编写调用,我也应该担心它可能具有不良副作用吗?
public class SomeController : Controller {
public async Task<ActionResult> SomeAction() {
var result = await new MyRepository.GetFirstFooAsync();
[...]
}
}
我之所以问这个问题,是因为我认为互联网智慧反对部分使用 .ConfigureAwait(false)
,因此即使它们针对其他组件,我也应在所有其他异步调用中使用 .ConfigureAwait(false)
。然而,我不确定我是否正确理解/解释了上述建议 - 如果我有疑问,请指出我的错误。如果我正确关注,请您提供一个示例,其中部分使用 .ConfigureAwait(false)
将会导致问题,并且提供多个 Async()
调用时如何使用 .ConfigureAwait(false)
的示例。