HttpClient.线程池中没有足够的空闲线程来完成操作

本文关键字:线程 操作 HttpClient | 更新日期: 2023-09-27 18:08:11

我每秒钟调用一次下面的代码来轮询相机,但是在运行一两天之后,它停止工作了。

public List<CameraEvent> GetEventsSince(CaptureTime afterDateTime)
{
    string uri = string.Format(
                    "http://{0}/ISAPI/channels/1/events/detect", _ipAddress);
    using (var client = new HttpClient())
    {
        client.Timeout = TimeSpan.FromSeconds(5);
        AddBasicAuth(client);
        try
        {
            HttpResponseMessage response =
                client.PostAsync(
                    uri, new StringContent(GetPicTimeXml(afterDateTime))).Result;
            logger.Debug(
                string.Format("Status code response={0}", response.StatusCode));
            if (response.StatusCode == HttpStatusCode.Unauthorized ||
                response.StatusCode == HttpStatusCode.Forbidden)
            {
                // 401
                currentState = 2;
                return new List<CameraEvent>();
            }
            if (response.StatusCode == HttpStatusCode.OK)
            {
                // OK
                currentState = 0;
            }
            List<CameraEvent> events = new CameraHttpResponseHandler()
                                           .HandleHttpResponse(response);
            AppendPlateImages(events);
            return events;
        }
        catch (AggregateException ex)
        {
            //if (ex.InnerException is TaskCanceledException)
            //{
            //    // Timeout
            //    currentState = 1;
            //}
            logger.Error("AggregateException", ex);
        }
        catch (Exception ex)
        {
            logger.Error("Generic exception", ex);
        }
        return new List<CameraEvent>();
    }
}
我得到的错误是:

2015-08-17 07:59:57,310 [16] ERROR CameraHttpClient AggregateException系统。AggregateException:发生了一个或多个错误。--->系统。没有足够的空闲线程

调用GetEventsSince的父线程是在循环中运行的background worker线程。

有没有人看到这个问题,或者对什么可能导致线程耗尽有任何建议?

HttpClient.线程池中没有足够的空闲线程来完成操作

很难说,但如果线程池不足的根本原因是这个方法,那么它是一个很好的例子,说明为什么异步代码在服务器上是有益的。

HttpClient是一个异步API,这意味着如果你正确地调用await,你释放一个线程并将其发送回线程池,直到调用返回。通过调用.Result,您将在整个调用期间阻塞线程。假设这个方法从开始到结束需要几秒钟,并且99.9%的时间都在等待I/O(这不是一个不合理的猜测)。它的方式是,您在100%的时间内消耗线程。如果您将其重构为异步运行,则线程消耗将下降到0.1%的时间,并且线程池平均会突然变得更满。

因此,我将首先标记方法async(使用Task<List<CameraEvent>>作为返回类型),并使用await而不是使用异步api的.Result。我不知道CameraHttpResponseHandler.HandleHttpResponse到底做了什么,但我猜在I/O上也有阻塞,它也应该被转换,并使用await调用。

这暗示了根应用程序如何调用这个方法。我需要看到的代码建议最好的方法。TPL Dataflow可能很适合这里—它不仅有助于定期调用异步方法,而且还支持限制并发性,作为防止此类问题的一种保障。