我的所有线程都被HTTPClient.GetAsync()卡住了,但我的应用程序从未发送过任何请求
本文关键字:我的 应用程序 请求 任何 线程 HTTPClient GetAsync | 更新日期: 2023-09-27 18:21:54
我正在处理大量的API请求,我注意到有时应用程序似乎在HTTPClient.GetAsync()上"卡住"了。我有一个请求队列,每次发出请求时,它都会为它做一个任务,这样它就可以快速移动到下一个请求,而不必等待它返回。
几乎是随机的,线程会开始堆积,直到我达到线程池的限制。它们都堆积在HttpResponseMessage response = client.GetAsync(BaseUrl + endpoint + ToQueryString(request)).Result;
上。如果我在HTTPClient上设置了超时,它永远不会超时。通过使用microsoft网络监视器,我已经能够确定当这种情况开始发生时,实际上没有发送任何请求。
这是不可靠的可重复性。在这种情况发生之前,我可以处理100个请求,或者10000个请求。
违规代码:
private T Get<T>(string endpoint, IRequest request) where T : class
{
return Get2<T>(endpoint, request).Result;
}
private async Task<T> Get2<T>(string endpoint, IRequest request) where T : class
{
var client = InitHttpClient();
string debug = BaseUrl + endpoint + ToQueryString(request);
HttpResponseMessage response = await client.GetAsync(BaseUrl + endpoint + ToQueryString(request)).ConfigureAwait(false);
//HttpResponseMessage response = client.GetAsync(BaseUrl + endpoint + ToQueryString(request)).Result;
string body = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
T result = JsonConvert.DeserializeObject<T>(body, _serializerSettings);
return result;
}
var error = JsonConvert.DeserializeObject<HelpScoutError>(body);
throw new HelpScoutApiException(error, body);
}
注意:阅读后:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html我把我的代码切换到你上面看到的测试。线程现在卡在:return Get2<T>(endpoint, request).Result;
上
编辑:更改前的代码:
private async <T> Get<T>(string endpoint, IRequest request) where T : class
{
var client = InitHttpClient();
string debug = BaseUrl + endpoint + ToQueryString(request);
HttpResponseMessage response = client.GetAsync(BaseUrl + endpoint + ToQueryString(request)).Result;
string body = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
T result = JsonConvert.DeserializeObject<T>(body, _serializerSettings);
return result;
}
var error = JsonConvert.DeserializeObject<HelpScoutError>(body);
throw new HelpScoutApiException(error, body);
}
我能做些什么来调试它?对造成这种情况的原因有什么见解吗?
编辑2:经过更多的搜索,这可能是由某种死锁引起的吗?我正在为每个请求制作一个新的HTTPClient(我知道这有点糟糕),所以我认为这不会发生。
Edit3:这是我正在使用的API客户端,任何Get
方法都会导致我发布的代码。https://github.com/Selz/HelpScoutNet/blob/master/src/HelpScoutClient.cs
这个问题的答案是,这很可能是一个死锁问题。
我试图在多个线程上以异步方式使用HttpClient,这会周期性地导致我只能确定的死锁场景。
我通过为这个库构建一个异步客户端来纠正这一问题,确保anyc方法在整个调用堆栈中都已用完。在使用了完全异步兼容的库之后,问题就消失了。