I am working on an old ASP.NET MVC 4 website running on .NET v4.6.1 that I cannot change and I am calling a web api2 using HttpClient
.
As you know, the call requires is an async call, however everywhere else, the code is not using async, and I decided to use refit to make my life easier.
However I am forced to do the following all over the shop:
myRefitHttpClient.GetSomestuff(whatever).GetAwaiter().GetResult();
Is there a better way than the above blocking code if you need to do sync over async?
Many thanks for any reply
CodePudding user response:
As mentioned in the comments, sync-over-async is always dangerous in .NET Framework on ASP.NET.
To avoid deadlocks, the following pattern (as described in Figure Six of Stephen Cleary's article allows you to split out your async request from your synchronous method call:
public SomeStuff GetSomestuff(Whatever whatever)
{
return GetSomestuffAsync(whatever).GetAwaiter().GetResult();
}
public async Task<SomeStuff> GetSomestuffAsync(Whatever whatever)
{
// Do NOT queue a synchronization context continuation.
return myRefitHttpClient.GetSomestuff(whatever).ConfigureAwait(false);
}
You can then verify via a unit test that your code does not deadlock with the AsyncContext
library from Stephen Cleary by simulating a synchronization context.
[TestMethod]
public void Verify_DoesNotDeadlock()
{
AsyncContext.Run(() =>
{
var whatever = new Whatever();
var response = service.GetSomestuff(whatever);
Assert.IsNotNull(response);
});
}