GetAsync:不返回HttpResponseMessage

时间:2016-03-16 10:52:56

标签: c# asynchronous async-await webapi2 httpresponsemessage

应用应从 LoginUser()接收 httpresponsemessage ,但它没有响应。

    private void button1_Click(object sender, EventArgs e)
    {
        if (LoginUser(tUser.Text, Password.Text).Result.IsSuccessStatusCode)
        {
            Notifier.Notify("Successfully logged in.. Please wait!");

        }
        else
        {
            Notifier.Notify("Please check your Credential..");
        }            
    }
    public async Task<HttpResponseMessage> LoginUser(string userid, string password)
    {
        string URI = "http://api.danubeco.com/api/userapps/authenticate";

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("c291cmF2OmtheWFs");

            using (var response = await client.GetAsync(String.Format("{0}/{1}/{2}", URI, userid, password)))
            {
                return response;
            }
        }
    }

请帮忙!

1 个答案:

答案 0 :(得分:6)

您正在阻止UI线程并导致死锁。 From Stephen Cleary's blog(只需使用GetJsonAsync方法替换LoginUserGetStringAsync替换为client.GetAsync):

  

所以这就是从顶级方法开始的情况   (Button1_Click for UI / MyController.Get for ASP.NET):

     
      
  1. 顶级方法调用GetJsonAsync(在UI / ASP.NET上下文中)。

  2.   
  3. GetJsonAsync通过调用HttpClient.GetStringAsync(仍在上下文中)启动REST请求。

  4.   
  5. GetStringAsync返回未完成的任务,表示REST请求未完成。

  6.   
  7. GetJsonAsync等待GetStringAsync返回的任务。捕获上下文并将用于继续运行   GetJsonAsync方法稍后。 GetJsonAsync返回未完成的任务,   表示GetJsonAsync方法未完成。

  8.   
  9. 顶级方法同步阻止GetJsonAsync返回的任务。这会阻止上下文线程。

  10.   
  11. ...最终,REST请求将完成。这样就完成了GetStringAsync返回的任务。

  12.   
  13. GetJsonAsync的延续现在已准备好运行,它等待上下文可用,以便它可以在上下文中执行。

  14.   
  15. 死锁。顶级方法是阻塞上下文线程,等待GetJsonAsync完成,GetJsonAsync正在等待   上下文是免费的,所以它可以完成。

  16.   

简单易用的解决方案(也来自博客):

  
      
  1. 在“库”异步方法中,尽可能使用ConfigureAwait(false)。
  2.   
  3. 不要阻止任务;一直使用async。
  4.   

第二个解决方案建议您将button1_Click更改为:

private async void button1_Click(object sender, EventArgs e)
{
    if ((await LoginUser(tUser.Text, Password.Text)).IsSuccessStatusCode)
    {
        Notifier.Notify("Successfully logged in.. Please wait!");

    }
    else
    {
        Notifier.Notify("Please check your Credential..");
    }            
}