c# - HttpClient.PostAsync ThreadPool 中没有足够的空闲线程来完成操作

标签 c# multithreading http threadpool

我每秒调用一次下面的代码来轮询摄像头,但运行一两天后,它就停止工作了。

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 System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: There were not enough free threads in the ThreadPool to complete the operation.

调用 GetEventsSince 的父线程是一个 background worker 线程,如果这有任何区别的话,它会在一个循环中运行。

有没有人见过这个问题或对可能导致线程用完的原因有任何建议?

最佳答案

很难确定,但如果线程池饥饿的根本原因是这种方法,那么它就是为什么异步代码对服务器有益的一个很好的例子。

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

所以我首先要标记方法 async (使用 Task<List<CameraEvent>> 作为返回类型)并使用 await而不是 .Result使用异步 API 的地方。我不知道是什么CameraHttpResponseHandler.HandleHttpResponse确实如此,但我猜那里也有 I/O 阻塞,它也应该被转换并使用 await 调用.

这对根应用程序调用此方法的方式有影响。我需要查看该代码以建议最佳方法。 TPL Dataflow可能很适合这里 - 它不仅有助于定期调用异步方法,而且还支持限制并发性,作为防止此类问题的一种保护措施。

关于c# - HttpClient.PostAsync ThreadPool 中没有足够的空闲线程来完成操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32046657/

相关文章:

c# - 等待 .NET 4.0 中的替代方案?

java - wait() 调用时出现 IllegalMonitorStateException

定期调用已创建线程的函数(手动调度)

php - 似乎无法将 JSONObject 从 android 发送到远程服务器

c# - Itextsharp : PDF size too large when including images

c# - 如何使用 Linq (C#) 分隔所有连续的对象

c# - 为什么不允许使用 lock(<integer var>),但允许使用 Monitor.Enter(<integer var>)?

c - C程序中线程内的多线程

node.js - 如何过早关闭 http.ServerResponse?

javascript - 访问从工厂返回的对象