我发出了大量的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);
}
我能做些什么来调试它?有什么原因会导致这种情况吗?
Edit2:经过进一步的搜索,这会不会是由某种死锁引起的?我为每个请求创建了一个新的HTTPClient (我知道这有点糟糕),所以我认为这不会发生。
Edit3:这是我正在工作的API客户端,任何Get
方法都会指向我之前发布的代码。https://github.com/Selz/HelpScoutNet/blob/master/src/HelpScoutClient.cs
发布于 2018-10-24 03:18:05
这个问题的答案是,这很可能是一个死锁问题。
我试图在多线程上以异步方式使用HttpClient,这将周期性地导致我只能确定的死锁情况。
我为这个库构建了一个异步客户端,确保anyc方法在整个调用堆栈中都被使用,从而纠正了这个问题。在使用完全异步兼容库之后,这个问题消失了。
https://stackoverflow.com/questions/33715729
复制相似问题