1
votes

I am facing problem in calling HttpClient class and async call. I call the function List() from page_load. The calls return from the line HttpResponseMessage response = await client.GetAsync(str); and never comes back to finish it.

I don't understand what mistake I am doing. Following is my code:

        protected void Page_Load(object sender, EventArgs e)
        {
            Task<string> s= List(product); 
        }

        protected async Task<string> List(string ProductType)
        {
            string str = "http://xx.xx.com/wiki/api.php";


            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", "username", "password"))));
                HttpResponseMessage response = await client.GetAsync(str);

                response.EnsureSuccessStatusCode();

                string content = await response.Content.ReadAsStringAsync();
            }
            return content;
         }

It never executes following lines.

response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();

Please help. Thanks in advance.

1

1 Answers

1
votes

You never show what happens to the task in Page_Load, but given your symptoms and the fact that Page_Load is not async, I'm betting that you're calling Result or Wait instead of awaiting it.

When you do that, you cause a deadlock. The link to my blog explains this in detail, but the gist is that await will capture and restore the current "context". In ASP.NET, this is a request context, and the request context only allows one thread executing in it at a time. So, if you call Result or Wait (while you're in the request context), you'll block a thread in that request context until the Task<string> completes. Meanwhile, when the HttpClient gets its response, it tries to resume after the await client.GetAsync(str). But the request context will only allow one thread in at a time, and that thread is blocked waiting for the Task to complete. Since List cannot complete because the context is busy, you have a deadlock.

To prevent deadlocks, follow these two best practices (from my recent MSDN article):

  1. Use async all the way. That is, use await instead of Result or Wait.
  2. Use ConfigureContext(false) in your "library" code, i.e., every await in List should actually be await ... .ConfigureAwait(false);