Reputation: 590
I have written two codes:
code block 1:
Stream dataStream;
using (var response = (HttpWebResponse)req.GetResponse())
{
dataStream = response.GetResponseStream();
}
//Open the stream using a StreamReader for easy access
using (var reader = new StreamReader(dataStream))
{
data = reader.ReadToEnd();
}
code block 2:
Stream dataStream;
using (var response = (HttpWebResponse)req.GetResponse())
{
dataStream = response.GetResponseStream();
//Open the stream using a StreamReader for easy access
using (var reader = new StreamReader(dataStream))
{
data = reader.ReadToEnd();
}
}
Code block 1 is throwing error: stream is not reachable
.
While progmatically i think both code will work same.
I added using block in to whole statment in code block 2 and it's working.
But I'm confused why is it throwing error in code block 1
Upvotes: 1
Views: 352
Reputation: 17509
Because post compilation (in IL), your code gets converted to the following
Code Block: 1
HttpWebResponse response=null;
Stream dataStream;
try
{
response = (HttpWebResponse) req.GetResponse();
dataStream = response.GetResponseStream();
}
finally
{
if(response!=null)
((IDisposable)response).Dispose();
}
StreamReader reader = null;
try
{
//DataStream is accessed AFTER response object is disposed
reader = new StreamReader(dataStream);
data = reader.ReadToEnd();
}
finally
{
if(reader!=null)
reader.Dispose();
}
Code Block: 2
HttpWebResponse response=null;
Stream dataStream;
try
{
response = (HttpWebResponse) req.GetResponse();
dataStream = response.GetResponseStream();
StreamReader reader = null;
try
{
//DataStream is accessed while response object is alive, and connected (not disposed)
reader = new StreamReader(dataStream);
data = reader.ReadToEnd();
}
finally
{
if (reader != null)
reader.Dispose();
}
}
finally
{
if(response!=null)
((IDisposable)response).Dispose();
}
As you can see, in CodeBlock1, you are trying to access stream which is trying to read from a Disposed (and dis-connected) HttWebResponse object.
Upvotes: 0
Reputation: 7430
The using
statement ensures that the scoped object has the Dispose function called on it when the execution reaches the final bracket }
which means the HttpWebResponse object is out of scope in the second using block.
Although you have saved your stream in the datastream
variable the stream itself has not been read and that is done when you call ReadToEnd()
. And as the HttpWebResponse is out of scope or Disposed then you are getting the exception you received.
Upvotes: 1
Reputation: 39348
A Stream
is not a block of data, but a way to read that data from "somewhere".
When you dispose of that response (by exiting the using-block) you break the connection to that "somewhere". This means you can't read from that stream anymore.
Your second example keeps that connection alive until you are done reading it.
Upvotes: 1
Reputation: 82534
the using
block provides you easy and correct use of objects that are disposable. therefor, anything that is initialized in the using
statement will be constidered as disposed after the using
block, even if you declare the variable outside of the using
statement.
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.
Upvotes: 1
Reputation: 610
Rohit, the first code block is throwing error because, once you close the braces for the using clause, the object is considered as disposed. i.e. the object is left for the GC to collect. The scope of the stream in code block 1 had expired before the second using statement.
The right way to access the stream is the second code block.
Upvotes: 2
Reputation: 16423
Based upon the behavior you have specified, it would seem that when the HttpWebResponse
is disposed, it disposes of the response stream.
Upvotes: 5