Все мои потоки зависают в HTTPClient.GetAsync(), но из моего приложения никогда не отправляются запросы
Я делаю большое количество запросов 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
1 ответ
Ответ на этот вопрос заключается в том, что это, скорее всего, проблема взаимоблокировки.
Я пытался использовать HttpClient в асинхронном режиме в нескольких потоках, это периодически приводило к тому, что я могу только убедиться, что это сценарий тупика.
Я исправил это, создав асинхронный клиент для этой библиотеки, гарантируя, что методы anyc используются во всем стеке вызовов. После использования полностью асинхронной совместимой библиотеки проблема исчезла.