Reputation: 25945
I've a web API on server side as below. It is using async-await pattern. All these methods are present inside MyClassController
class
[Route("install")]
public async Task<IHttpActionResult> InstallProduct()
{
Log("milestone1");
Install();
Log("milestone6");
}
private bool Install()
{
MyClass.Register();
Log("milestone5");
}
private static async void Register()
{
Log("milestone2");
using (HttpClientHandler handler = new HttpClientHandler())
{
using (var client = new HttpClient(handler))
{
var method = "http://BaseUrlOfWebsite#2/api/applications";
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
//make POST API call into website # 2
var response = await client.PostAsync(method, form);
Log("milestone3");
}
}
}
Log("milestone4");
}
Overall call is like this:
Client code -> install
API on website # 1 -> applications
API on website # 2
My expected log statements are in below order:
milestone1
milestone2
milestone3
milestone4
milestone5
milestone6
Actual log order that I see in log files is as below:
milestone1
milestone2
milestone5
milestone6
milestone3
milestone4
Code doesn't causes error anywhere but it returns 500 internal server error code to calling client. I've two questions here:
Register
method should get blocked while calling external website as I'm using await
while waiting for response.Note: Same logs get printed in expected order when I debug the install
API with debugger attached in Visual Studio.
Update: If I make the call to external website client.PostAsync
run synchronously forcefully using Task.Run
then I get 200 OK response. Why web API results in error if I can fire and forget the call to external website and my remaining code can run synchronously to finish the web API call.
Upvotes: 1
Views: 4522
Reputation: 469
In general, when you see async void in your code it’s bad news, because:
you can’t wait for its completion (as mentioned in this post already) any unhandled exceptions will terminate your process (ouch!)
Suppose you have a timer event that fires every once in a while and you want to do some asynchronous processing inside the handler, so you proceed to write something along the lines of:
var timer = new Timer();
timer.Elapse += OnTimerFired;
timer.Interval = 1000;
timer.Start();
...
private static async void Register()
{
await Task.Delay(1000);
// this is going to terminate your process!
throw new Exception();
}
Upvotes: 1
Reputation: 538
Register
method is async, it returns void, instead of Task, which could be awaited.
And instead of awaiting for task your code is running synchronously.
[Route("install")]
public async Task<IHttpActionResult> InstallProduct()
{
Log("milestone1");
await Install();
Log("milestone6");
}
private async Task Install()
{
await MyClass.Register();
Log("milestone5");
}
private static async Task Register()
{
Log("milestone2");
using (var handler = new HttpClientHandler())
{
using (var client = new HttpClient(handler))
{
var method = "http://BaseUrlOfWebsite#2/api/applications";
using (MultipartFormDataContent form = new MultipartFormDataContent())
{
//make POST API call into website # 2
var response = await client.PostAsync(method, form);
Log("milestone3");
}
}
}
Log("milestone4");
}
Upvotes: 3