Why using .Result in ASP.NET Core doesn't produce deadlock?

Viewed 527

I have read this article and from what I understand, calling .Result on the Task received from an async method should produce a deadlock on one of the controller's actions.

I have the following code on which I have tried to reproduce what should have behaved like a deadlock:

// 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);
    }
}

On the https://localhost:44316/api/values I have another Web Application that simply returns me a valid json.

The code runs flawlessly even though as stated in the article, it should produce a deadlock as the continuation of the GetStringAsync method should be waiting for the ASP.NET context which should be held by the first Get method (the request thread).

Why I am not able to reproduce the deadlock described in the article, what am I missing?

1 Answers

The article is referring to the behavior of a particular sync context in ASP.NET; it doesn't apply to .NET Core at all, and even in ASP.NET this has been changed in more recent times to one that is more sympathetic to the TPL, but I suspect that if you configure ASP.NET (not "Core") with either:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />

or:

<httpRuntime targetFramework="4.5" />

then you'll see the behavior being discussed.

However! You still should not do what you are doing; it is a terrible idea to access .Result unless you know a task is completed; await is the preferred mechanism. Just because it doesn't explode in this case doesn't mean it is OK to do it.

Related