WCF Data Services Client does not close connections!

Have you ever worked with the WCF DataServices Client? I was contributing to the nuget project and experienced *some* problems. After a few operations (web request through either the WCF Data Service Context or manually through a WebRequest) operations started to time out. I used (the fabulous) reflector pro to digg into the sources. What you see here is a class utilized to return the result of a WCF Data Services request.  

namespace System.Data.Services.Client { using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Runtime; using System.Threading; internal class QueryResult : BaseAsyncResult { internal void Execute() { try { HttpWebResponse response = null; try { response = (HttpWebResponse) this.Request.GetResponse(); } catch (WebException exception) { response = (HttpWebResponse) exception.Response; if (response == null) { throw; } } this.SetHttpWebResponse(Util.NullCheck<HttpWebResponse>(response, InternalError.InvalidGetResponse)); if (HttpStatusCode.NoContent != this.StatusCode) { using (Stream stream = this.httpWebResponse.GetResponseStream()) { if (stream != null) { Stream asyncResponseStreamCopy = this.GetAsyncResponseStreamCopy(); this.responseStream = asyncResponseStreamCopy; byte[] asyncResponseStreamCopyBuffer = this.GetAsyncResponseStreamCopyBuffer(); long num = WebUtil.CopyStream(stream, asyncResponseStreamCopy, ref asyncResponseStreamCopyBuffer); if (this.responseStreamOwner) { if (0L == num) { this.responseStream = null; } else if (asyncResponseStreamCopy.Position < asyncResponseStreamCopy.Length) { ((MemoryStream) asyncResponseStreamCopy).SetLength(asyncResponseStreamCopy.Position); } } this.PutAsyncResponseStreamCopyBuffer(asyncResponseStreamCopyBuffer); } } } } catch (Exception exception2) { base.HandleFailure(exception2); throw; } finally { base.SetCompleted(); this.CompletedRequest(); } if (base.Failure != null) { throw base.Failure; } }

Have you seen it? The HttpWebResponse instance is never closed neither disposed. Let’s digg into the HttpWebResponse close method…

public override void Close() { if (Logging.On) { Logging.Enter(Logging.Web, this, "Close", ""); } if (!this.m_disposed) { this.m_disposed = true; Stream connectStream = this.m_ConnectStream; ICloseEx ex = connectStream as ICloseEx; if (ex != null) { ex.CloseEx(CloseExState.Normal); } else if (connectStream != null) { connectStream.Close(); } } if (Logging.On) { Logging.Exit(Logging.Web, this, "Close", ""); } }

The close method closes the network stream that is in the end associated with an tcp connection. A cite from the msdn documentation:

The response must be closed to avoid running out of system resources. The response stream can be closed by calling Stream.Close or Close.

This can be validated though a netmon trace:


The request I did manually (and closed properly) don’t keep a connection alive. The WCF Data Services Client calls do. This results in additional calls timing out.

Sad but true…

Add comment