为什么在 ASP.NET Core 中使用 .Result 不会产生死锁?

meJ*_*rew 3 .net c# task asp.net-core

我已阅读这篇文章,据我了解,调用.Result从异步方法接收的任务应该会在控制器的其中一个操作上产生死锁。

我有以下代码,我试图重现应该表现得像死锁的情况:

// GET api/values
[HttpGet]
public ActionResult<string> Get()
{
    return GetSomeValue().Result.ToString();
}

private async Task<JObject> GetSomeValue()
{
    using (var httpClient = new HttpClient())
    {
        var jsonString = await httpClient.GetStringAsync("https://localhost:44316/api/values");
        return JObject.Parse(jsonString);
    }
}
Run Code Online (Sandbox Code Playgroud)

https://localhost:44316/api/values有另一个 Web 应用程序,它只是返回一个有效的 json。

该代码运行完美,即使如本文所述,它应该会产生死锁,因为该GetStringAsync方法的延续应该等待应由第一个Get方法(请求线程)持有的 ASP.NET 上下文。

为什么我无法重现文章中描述的死锁,我错过了什么?

Mar*_*ell 5

本文涉及ASP.NET 中特定同步上下文的行为;它根本不适用于 .NET Core,甚至在 ASP.NET 中,这在最近也已更改为更支持 TPL 的一种,但我怀疑如果您配置 ASP.NET(不是“Core”) ") 与以下任一:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />
Run Code Online (Sandbox Code Playgroud)

或者:

<httpRuntime targetFramework="4.5" />
Run Code Online (Sandbox Code Playgroud)

然后你就会看到正在讨论的行为。

然而!你仍然不应该做你正在做的事.Result除非您知道任务已完成,否则访问是一个糟糕的主意;await是首选机制。在这种情况下,仅仅因为它不会爆炸并不意味着可以这样做。