4

I am having problems with some simple testing code that does bulk downloads from one of our restful services. It appears that the low level socket is not being released by the call to Dispose. Here is the basic code;

foreach(...)
{
  using(WebClient client = new WebClient())
  {
    string results = client.DownloadString("http://host/request");
    client.Dispose();
  }
}

This causes an exception after 255 loops. I tried adding this line (via some suggestions form another stackoverflow post).

System.Net.ServicePointManager.DefaultConnectionLimit = 500;

Then I get an exception after 500 loops. So, it seems to me the low level socket connection is not being released.

Has anyone else seen this issue? Do you know a work around.

Thanks

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
user493721
  • 53
  • 6
  • 1
    The `client.Dispose()` is unnecessary, that's what the `using` is for. – Pieter van Ginkel Nov 01 '10 at 15:55
  • Not an answer, but you don't need to call `Dispose` inside of a `using` block; the main point of the using block is that it ensure Dispose is automatically called. Also, you could use just one `WebClient` instance and put the `foreach` inside of the `using` block. – Jacob Nov 01 '10 at 15:56

3 Answers3

1

WebClient does not override the Dispose it inherits from Component.

There should not be a need to call the Dispose and I do not get the error you mentioned. Please mention the other stackoverflow post.

In fact, WebClient does not keep any state that would need dsiposing and is pretty stateless. Looking at the implementation in Reflector makes it obvious that it looks after the reasources in here (method DownloadDataInternal is called from DownloadString):

private byte[] DownloadDataInternal(Uri address, out WebRequest request)
{
    byte[] buffer2;
    if (Logging.On)
    {
        Logging.Enter(Logging.Web, this, "DownloadData", address);
    }
    request = null;
    try
    {
        request = this.m_WebRequest = this.GetWebRequest(this.GetUri(address));
        buffer2 = this.DownloadBits(request, null, null, null);
    }
    catch (Exception exception)
    {
        if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException))
        {
            throw;
        }
        if (!(exception is WebException) && !(exception is SecurityException))
        {
            exception = new WebException(SR.GetString("net_webclient"), exception);
        }
        AbortRequest(request);
        throw exception;
    }
    catch
    {
        Exception exception2 = new WebException(SR.GetString("net_webclient"), new Exception(SR.GetString("net_nonClsCompliantException")));
        AbortRequest(request);
        throw exception2;
    }
    return buffer2;
}
Aliostad
  • 80,612
  • 21
  • 160
  • 208
0

You could try calling GC.Collect to force the GC to run, seems that it might be the problem your having

Fredrik Leijon
  • 2,792
  • 18
  • 20
0

You could try using HttpWebRequest instead of WebClient. In my experience, I usually have an easier time doing what I want with that API, though using it isn't quite as easy. I believe you can control connections a lot easier with HttpWebRequest.

Jacob
  • 77,566
  • 24
  • 149
  • 228