我的所有线程都被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.GetAsync()卡住了,但我的应用程序从未发送过任何请求

这个问题的答案是,这很可能是一个死锁问题。

我试图在多个线程上以异步方式使用HttpClient,这会周期性地导致我只能确定的死锁场景。

我通过为这个库构建一个异步客户端来纠正这一问题,确保anyc方法在整个调用堆栈中都已用完。在使用了完全异步兼容的库之后,问题就消失了。