var _config = new HttpSelfHostConfiguration(ConfigurationManager.AppSettings["HttpApi.ListeningURL"]) { TransferMode = TransferMode.StreamedResponse };
I have a WebApi self-host application is configured to streaming the response.
And there is a HTTP GET action returns PushStreamContent
[HttpGet] public HttpResponseMessage GET(string domains, int version = 1) { // ... Func<Stream, HttpContent, TransportContext, Task> func = (stream, httpContent, transportContext) => { return Monitor(domainIDs, itemsPerDomain, version, httpContent, stream); }; HttpResponseMessage response = Request.CreateResponse(); response.StatusCode = HttpStatusCode.OK; response.Content = new PushStreamContent(func, new MediaTypeHeaderValue(CONTENT_TYPE)); return response; }
And the response is sent asynchronously
async Task Monitor(List<long> domainIDs , Dictionary<long, List<T2>> itemsPerDomain , int version , HttpContent httpContent , Stream stream ) { try { using (StreamWriter sw = new StreamWriter(stream, new UTF8Encoding(false))) {
sw.WriteLine("xxx"); // ... } } catch (CommunicationException) { // ignore } catch (Exception ex) { log.Error(ex); } finally { stream.Close(); stream.Dispose(); httpContent.Dispose(); log.Info("Dispose"); } }
If client terminates the connection when the server is sending the response.
An CommunicationException exception is thrown and its internal exception is System.Net.HttpListenerException. error code is1229.
You can note that I dispose everything possible in finally block.
but it still leaks completion port threads.
I monitor the completion port threads via
int availableCompletionPortThreads; ThreadPool.GetAvailableThreads(out unused, out availableCompletionPortThreads)
The availableCompletionPortThreads does not restore when the above exception occurs no matter how long I wait. And it only happens for this kind of exception -- client terminates the connection. And it can bring down the application by exhausting the completion port threads.
Why is the completion port thread is leaking?