When to call WebResponse.Close()
Asked Answered
S

4

15
WebResponse response;
try
{                
 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
 request.Timeout = 20000;
 response = request.GetResponse();

 request = (HttpWebRequest)WebRequest.Create(url2);
 response = request.GetResponse();
}
catch(Exception ex)
{
 //do something
}              
finally
{
}

where should response.Close() be called?

  • after every GetResponse() in try?

  • after last GetResponse() in try - once?

  • in finally block?
Slantwise answered 26/7, 2009 at 12:15 Comment(0)
I
26

None of the above. You should be using a using block:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 20000;
using (WebResponse response = request.GetResponse())
{
    using (var stream = response.GetResponseStream())
    {
        using (var reader = new StreamReader(stream))
        {
            var result = reader.ReadToEnd();
            // Do something with result
        }
    }
}

A using block will ensure that the Dispose method is called, whether or not there is an exception. Dispose will do the same thing as Close.

using (var d = new DisposableClass()){code;}

is equivalent to:

DisposableClass d = null;
try
{
    d = new DisposableClass();
    code;
}
finally
{
    if (d != null)
        ((IDisposable)d).Dispose();
}
Interloper answered 26/7, 2009 at 12:27 Comment(7)
For a more detailed explanation, you could show how all those using statements get converted to try/finally statements :) Only reason I say this is because he asked if he should put it in a finally statement, which you are in a sense doing... Obviously in a cleaner / easier to read manner.Calces
Surely this must be doable without using 'using', just the standard try catch finally blocks?Bukhara
Is it mandatory to dispose the WebResponse instance? I don't see dispose in Vs2008's intellisense.Supinator
Hmm when I use ILSpy (instead of .$$$ Reflector) I see an IDisposable interface. The only thing dispose does is run Close().Supinator
@Michel: so does that answer your question? My answer is: if it implements IDisposable, and if you created it, then you need to Dispose of it.Interloper
@Michel: I don't know. Were you using VB.NET? By default it doesn't show all details.Interloper
This appears to have problems. If you kill the process while the request is being made, it will come back with a user-unhandled exception for ObjectDisposedException - Cannot access a disposed object. in Socket.cs bool SendToAsync()Habitue
A
1

Put it in the finally block. As per MSDN:

The finally block is useful for cleaning up any resources allocated in the try block as well as running any code that must execute even if there is an exception. Control is always passed to the finally block regardless of how the try block exits.

Amphibian answered 26/7, 2009 at 12:24 Comment(1)
But if he puts response.Close() in finally he will get a 'use of unasigned variable' error.Bukhara
L
0

Note that nested using blocks don't need curly braces, improving readability. So John Saunder's code could be written:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 20000;
using (WebResponse response = request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
    var result = reader.ReadToEnd();
    // Do something with result
}

VS.NET understands that such nested blocks don't need indenting. Note btw that if you know the encoding of the response or are going to ignore it anyhow, WebClient provides a simpler API - missing header information, so Header-based (transfer/text) encoding detection becomes impossible, but otherwise it works fine.

Labrador answered 26/7, 2009 at 13:34 Comment(2)
I would argue that this reduces readability. I almost always add braces, even on single-line if statements, except for rare cases like "if (simple-condition) return;"Interloper
For short bits of code maybe - for real files adding these unnecessary braces on redundant lines means that your code becomes much longer and less fits on one screen, meaning you'll have less overview. The real hint anyhow should be indentation, and VS.NET automatically indents such code in a non-confusing fashion.Labrador
C
-1

I would suggest the below

        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.google.com");
            request.Timeout = 20000;
            using (var response = request.GetResponse())
            {
                //Do something with response.
            }


            request = (HttpWebRequest)WebRequest.Create("http://www.bing.com");
            using (var response = request.GetResponse())
            {
                //Do somehing with response
            }
        }
        catch (Exception ex)
        {
            //do something
        }
        finally
        {
        }
Cop answered 26/7, 2009 at 12:26 Comment(3)
Surely you need to dispose/Close the first "request" instance, since you just overwrite that instance with a new one, you're at the mercy of the Garbage collector to when that first one gets disposed.Hamsun
WebRequest does not implement IDisposable.Interloper
There is no reason for a finally block here. Also, without having some actual code in the catch, this answer may leave the false impression that try/catch is required around all code.Interloper

© 2022 - 2024 — McMap. All rights reserved.