Async call with await in HttpClient never returns

C#AsynchronousAsync AwaitDotnet Httpclient

C# Problem Overview


I have a call I am making from inside a xaml-based, C# metro application on the Win8 CP; this call simply hits a web service and returns JSON data.

HttpMessageHandler handler = new HttpClientHandler();

HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");

var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);
        

It hangs at the await but the http call actually returns almost immediately (confirmed through fiddler); it is as if the await is ignored and it just hangs there.

Before you ask - YES - the Private Network capability is turned on.

Any ideas why this would hang?

C# Solutions


Solution 1 - C#

Check out this answer to my question which seems to be very similar.

Something to try: call ConfigureAwait(false) on the Task returned by GetStreamAsync(). E.g.

var result = await httpClient.GetStreamAsync("weeklyplan")
                             .ConfigureAwait(continueOnCapturedContext:false);

Whether or not this is useful depends on how your code above is being called - in my case calling the async method using Task.GetAwaiter().GetResult() caused the code to hang.

This is because GetResult() blocks the current thread until the Task completes. When the task does complete it attempts to re-enter the thread context in which it was started but cannot because there is already a thread in that context, which is blocked by the call to GetResult()... deadlock!

This MSDN post goes into a bit of detail on how .NET synchronizes parallel threads - and the answer given to my own question gives some best practices.

Solution 2 - C#

Just a heads up - if you miss the await at the top level in an ASP.NET controller, and you return the task instead of the result as a response, it actually just hangs in the nested await call(s) with no errors. A silly mistake, but had I seen this post it might have saved me some time checking through the code for something odd.

Solution 3 - C#

Disclaimer: I don't like the ConfigureAwait() solution because I find it non-intuitive and hard to remember. Instead I came to the conclusion to wrap non awaited method calls in Task.Run(() => myAsyncMethodNotUsingAwait()). This seems to work 100% but might just be a race condition!? I'm not so sure what is going on to be honest. This conclusion might be wrong and I risk my StackOverflow points here to hopefully learn from the comments :-P. Please do read them!

I just had the problem as described and found more info here.

The statement is: "you can't call an asynchronous method"

await asyncmethod2()

from a method that blocks

myAsyncMethod().Result

In my case I couldn't change the calling method and it wasn't async. But I didn't actually care about the result. As I remember it also didn't work removing the .Result and have the await missing.

So I did this:

public void Configure()
{
    var data = "my data";
    Task.Run(() => NotifyApi(data));
}

private async Task NotifyApi(bool data)
{
    var toSend = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
    await client.PostAsync("http://...", data);
}

In my case I didn't care about the result in the calling non-async method but I guess that is quite common in this use case. You can use the result in the calling async method.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionkeithwarren7View Question on Stackoverflow
Solution 1 - C#Benjamin FoxView Answer on Stackoverflow
Solution 2 - C#bozzleView Answer on Stackoverflow
Solution 3 - C#CodingYourLifeView Answer on Stackoverflow