0

I had this code working in .Net Core. We realized Core wasn't the best fit for us right now, so I have been refactoring in .Net 4.5.2 and when I call

HttpResponseMessage response = await client.GetAsync(passedlURI);

It just continues thinking indefinitely. I have pointed it at a local host version of my API and confirmed that the API is reading the header and returning my data correctly, I have used Postman to confirm that both the live API and localhost API are sending me the correct data. Here is my code so far:

enter image description here

Steve Eggering
  • 759
  • 2
  • 9
  • 23
  • I wonder if this Code compiles...Anyway!? Further this architecture doesn't make sense to me. – DotNetDev Apr 11 '17 at 18:43
  • Can you turn `public string CallAPI` into `public async Task CallAPI`? – mason Apr 11 '17 at 18:43
  • 1
    @DotNetDev You don't need a return statement in an `async Task` method. Only `async Task`. – mason Apr 11 '17 at 18:43
  • Right, it's void, thx – DotNetDev Apr 11 '17 at 18:45
  • Why did you use three methods here? Looks like they can all be combined into one. And you don't need any fields, just use local variables. – mason Apr 11 '17 at 19:20
  • @mason It's three different methods because eventually the RunAsync is going to have a switch in it based on an enumeration (Get, Post, Put, etc). The end goal is that we'll be able to call `APICall.CallAPI(URL, CallType.Post, User, Object)` and it will always return a JSON string that will be up to the caller to deserialize correctly. – Steve Eggering Apr 11 '17 at 19:45
  • I still don't see why you need to use fields. HttpClient implements [IDisposable](https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx). You need to dispose of it properly, and that's difficult when it's a field. None of those actually need to be fields. And you can accomplish what you just described with two methods instead of three. – mason Apr 11 '17 at 19:48

1 Answers1

8

Make sure to use .ConfigureAwait(false) with each of your await. Waiting synchronously on a task that internally awaits on the current synchronization context is a well-known cause of deadlocks in ASP.NET.

For instance, instead of:

await GetAPIAsync();

Do:

await GetAPIAsync().ConfigureAwait(false);

Of course, it would be even better if you didn't wait synchronously on a task to begin with.

The issue does not happen on ASP.NET Core because it doesn't use a custom synchronization context.

Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94