Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async call with await in HttpClient never returns

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?

like image 204
keithwarren7 Avatar asked Mar 27 '12 18:03

keithwarren7


People also ask

Does await stop the main thread?

Because await is only valid inside async functions and modules, which themselves are asynchronous and return promises, the await expression never blocks the main thread and only defers execution of code that actually depends on the result, i.e. anything after the await expression.

Is HttpClient asynchronous?

This example demonstrates a basic asynchronous HTTP request / response exchange. Response content is buffered in memory for simplicity. This example demonstrates an asynchronous HTTP request / response exchange with a full content streaming.

What does PostAsync return?

PostAsync(String, HttpContent)Send a POST request to the specified Uri as an asynchronous operation.

What does HttpClient GetAsync return?

The HTTP request is sent out, and HttpClient. GetAsync returns an uncompleted Task . AsyncAwait_GetSomeDataAsync awaits the Task ; since it is not complete, AsyncAwait_GetSomeDataAsync returns an uncompleted Task . Test5Controller. Get blocks the current thread until that Task completes.


2 Answers

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.

like image 75
Benjamin Fox Avatar answered Nov 08 '22 17:11

Benjamin Fox


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.

like image 10
bozzle Avatar answered Nov 08 '22 17:11

bozzle