使用HttpClient避免死锁

时间:2015-08-25 04:34:04

标签: c#

使用HttpClient并避免死锁的最佳方法是什么?我正在使用下面的代码,完全来自同步方法,但我担心它可能导致死锁。

我已经对.ConfigureAwait(false).GetAwaiter().GetResult()等功能进行了一些阅读,但我正在寻找最佳实践方法的输入。

代码不太准确,但足够接近。

public static bool TryRequest(string url, out response)
{    
    HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
    using (HttpClient client = new HttpClient())
    {
       HttpResponseMessage responseMessage = null;

       switch (verb)
       {
          case HttpVerb.Put:
             responseMessage = client.PutAsync(url, content).Result;
             break;
          case HttpVerb.Post:
             responseMessage = client.PostAsync(url, content).Result;
             break;
          case HttpVerb.Delete:
             responseMessage = client.DeleteAsync(url).Result;
             break;
          case HttpVerb.Get:
             responseMessage =  client.GetAsync(url).Result;
             break;
       }

       if (responseMessage.IsSuccessStatusCode)
       {
          responseContent = responseMessage.Content.ReadAsStringAsync().Result;
          statusCode = responseMessage.StatusCode;
       }
    }
}

2 个答案:

答案 0 :(得分:0)

我认为你的意思是避免阻止。死锁指的是两个或多个线程都无限期等待彼此完成的情况。

要避免在示例代码中出现阻塞,而不是同步等待结果,您只需要await非阻塞API调用:

HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
using (HttpClient client = new HttpClient())
{
    HttpResponseMessage responseMessage = null;

    switch (verb)
    {
        case HttpVerb.Put:
            responseMessage = await client.PutAsync(url, content);
            break;
        case HttpVerb.Post:
            responseMessage = await client.PostAsync(url, content);
            break;
        case HttpVerb.Delete:
            responseMessage = await client.DeleteAsync(url);
            break;
        case HttpVerb.Get:
            responseMessage = await client.GetAsync(url);
            break;
    }

    if (responseMessage.IsSuccessStatusCode)
    {
        responseContent = await responseMessage.Content.ReadAsStringAsync();
        statusCode = responseMessage.StatusCode;
    }
}

答案 1 :(得分:0)

就我而言,当我使用 a b c 0 1 2 7 1 2 3 6 2 3 4 5 时,我没有收到任何响应,当我尝试观察该问题时,调试器也在上述GetAsync()行上终止。我只能使用await client.GetAsync()来正确地获得响应,但是我看到很多人说它可能会导致像post这样的死锁,并且它也是同步的。我还特别在UI按钮单击事件中使用了此操作,不推荐

最后,我通过添加以下三行使其工作,我之前没有这三行(也许是问题所在):

client.GetAsync().Result

注意:

  1. ServiceBaseAddress必须以斜杠(/)结尾,并且相对URL 必须以无斜杠(/)开头
  2. 我的using (var client = new HttpClient()) { string relativeURL = "api/blah"; //These three lines - BaseAddress, DefaultRequestHeaders and DefaultRequestHeaders client.BaseAddress = new Uri(Constants.ServiceBaseAddress); client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync(relativeURL); ... } 的示例是Constants.ServiceBaseAddress

现在可以正常工作了,具有异步签名,没有死锁的困扰。希望这对某人有帮助。