I trying to use an API using Microsoft.Http. I followed the samples giving here http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client, but my task does not complete, keeps in status WaitingForActivation
Login button:
private void btnLogin_Click(object sender, EventArgs e) {
try {
var t = Api.LoginAsync( tbUsername.Text, tbPassword.Text);
t.Wait();
_Token = t.Result;
}
catch (Exception ex) {
ShowError(ex.Message);
}
}
Api class
static class Api {
private const string URLBase = "http://localhost:28929/";
public static async Task<string> LoginAsync(string Username, string Password ) {
using (var client = new HttpClient()) {
client.BaseAddress = new Uri(URLBase);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP POST
var VM = new Usuario() { Username = Username, Password = Password};
HttpResponseMessage response = await client.PostAsJsonAsync("api/login", VM);
if (response.IsSuccessStatusCode) {
return await response.Content.ReadAsAsync<string>();
}
else {
throw new ApplicationException("No se pudo ingresar. Error: " + response.StatusCode.ToString());
}
}
}
}
You have a deadlock there.
The
LoginAsync
method will run synchronously until the firstawait
(await client.PostAsJsonAsync("api/login", VM);
). Then it will return to the event handler, and the UI thread will be blocked on thet.Wait()
. When theawait client.PostAsJsonAsync("api/login", VM);
completes, the rest of the method is can run. The problem is that it has to run on the UI thread (on the same synchronization context), which is blocked, waiting for the task to complete. Deadlock.You have to use
await
in the event handler tooYou can find a detailed explanation on Stephen Cleary's blog.
You need to make your event handler
async
as well:You can try bypass this using:
Im not recomend it, but in some cases can help.