使用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;
}
}
}
答案 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
注意:
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
现在可以正常工作了,具有异步签名,没有死锁的困扰。希望这对某人有帮助。