I'm really annoyed when "using" block tampered my pre-created object. I have this piece of code
class Asset {
public Stream FileStream { get; set; }
public Asset(string fileName) {
FileStream = ...open a file stream...;
}
}
// Somewhere else
Asset asset = new Asset("file.txt");
using (var reader = new StreamReader(asset.FileStream)) {
//blah blah blah
}
// Somewhere else else
using (var reader2 = new StreamReader(asset.FileStream))
=> throws this exception:
System.ArgumentException: Stream was not readable.
Debugging step-by-step in Visual Studio helped me know that asset.FileStream has been disposed after the first "using" block.
Please help me to save his life :((
How can I create a clone stream from a stream?
I agree that the fact that readers close the underlying stream is dumb. The approach outlined in this article is to create a decorator class that wraps the Stream and has a no-op for the Close and Dispose methods. It's probably not worth the overhead, though, so you should consider just not using using for these readers.
Related
I am using StreamReader as shown below in my code:
string json = await new StreamReader(context.Request.Body).ReadToEndAsync();
// ... use json variable here in some other code
And I stumbled upon using statement. Is there any difference between my first statement vs using the using statement with StreamReader?
Should I be using using statement with StreamReader here in prod code?
string json;
using (var reader = new StreamReader(context.Request.Body))
{
json = await reader.ReadToEndAsync();
}
Is there any difference between my first statement vs using the using
statement with StreamReader
Yes. The difference is that when you wrap StreamReader in a using statement it will clear up some resources directly instead of waiting for the garbage collector. More specifically it will call Dispose() on StreamReader. You should almost always use using when the class implements IDisposable.
If your app simply uses an object that implements the IDisposable
interface, you should call the object's IDisposable.Dispose
implementation when you are finished using it.
Thanks to .NET Core being open source we can take a look at the source for StreamReader:
protected override void Dispose(bool disposing)
{
if (m_stream != null)
{
if (disposing)
{
m_stream.Close();
}
m_stream = null;
m_buffer = null;
m_curBufPos = 0;
m_curBufLen = 0;
}
m_disposed = true;
}
As you can see it calls Close() on the stream, which (according to the docs) in turn will call Dispose() on the stream itself.
Correctly disposing objects can be crucial when working with larger objects or streams. However, I will try to target your other question.
Should I be using using statement with StreamReader here in prod code?
Yes, no and maybe. In your partical case you have a context.Request.Body as a Stream (which I assume is from HttpContext). There is no need for the StreamReader to close that particular stream. It will be disposed correctly (later) anyway. Also, there might be some other resource that need access to that particual stream later in the pipeline.
Generally, if the class implements IDisposable then you should wrap it in a using. But here I think that you have two better choices:
1.
If you actually have a json (as your variable suggest), you can deserialize it directly using JsonSerializer found in System.Text.Json.JsonSerializer:
YourModel model = await System.Text.Json.JsonSerializer.DeserializeAsync<YourModel>(context.Request.Body);
UPDATE: Or if you are using .NET 5 you have access to HttpResponseJsonExtensions and can use ReadFromJsonAsync. Then you can simply try the following:
YourModel model = await context.Request.ReadFromJsonAsync<YourModel>();
Thanks to caius-jard.
2.
Use the overload of StreamReader that doesn't close the stream.
string json;
using (var reader = new StreamReader(stream, Encoding.UTF8, true, -1, true))
{
json = await reader.ReadToEndAsync();
}
So, to sum up. Yes, there is a difference when using using. However, in your particular case you have better options.
Check out this link
https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/
In short: "using" statement ensures that managed/unmanaged resource object disposes correctly and you don't have to call "Dispose" method explicitly even there is any execeptions occured within the using block
You can read further from Microsoft official site too
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement#:~:text=The%20using%20statement%20calls%20the,t%20be%20modified%20or%20reassigned.
I am trying to ensure my coding follows correct disposal of objects so I am enforcing these rules as errors. But I am having trouble with this section of code
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
class MyClass
{
public String ToXml()
{
var objSerializer =
new DataContractSerializer(GetType());
var objStream = new MemoryStream();
StreamReader objReader;
String strResult;
try
{
// Serialize the object
objSerializer.WriteObject(objStream, this);
// Move to start of stream to read out contents
objStream.Seek(0, SeekOrigin.Begin);
objReader = new StreamReader(objStream);
try
{
// Read Contents into a string
strResult = objReader.ReadToEnd();
}
finally
{
objReader.Dispose();
}
}
finally
{
if (objStream != null)
{
// objStream.Dispose();
}
}
return strResult;
}
}
If I comment out objStream.Dispose() I get CA2000 as I am not disposing the object but if I remove the comment it then says I am disposing more than once.
What else is disposing the object? or am I just doing this wrong when dealing with multiple streams?
This scenario has been annoying me as well now. Every couple of years I decide to refresh myself of the code analysis "rules" by running fxcop or the now built-in code analysis in Visual Studio.
I originally wrote this code, thinking I was being a good citizen for properly using usings to dispose:
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(eop.m_Ciphertext, 0, eop.m_Ciphertext.Length);
}
decrypted = msDecrypt.ToArray();
}
This block of code results in a CA2202 "Do not dispose objects multiple times" The great irony about this rule, is that it's not really about a problem with your code, as much as it is protecting you about a problem in others code. Microsoft has always had a decent amount of documentation about how the Dispose pattern (http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx) should be implmented. However, by looking at the details of this code analysis rule (http://msdn.microsoft.com/en-us/library/ms182334.aspx) it reveals the purpose of this rule
"A correctly implemented Dispose method can be called multiple times
without throwing an exception. However, this is not guaranteed and to
avoid generating a System.ObjectDisposedException you should not call
Dispose more than one time on an object."
In short, this rule is all about protecting yourself from people who don't follow the rules.
Naturally I modified the code to look like this:
MemoryStream msDecrypt = new MemoryStream()
//using (MemoryStream msDecrypt = new MemoryStream())
//{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(eop.m_Ciphertext, 0, eop.m_Ciphertext.Length);
}
decrypted = msDecrypt.ToArray();
//}
Now everybody on this stack overflow post is painfully aware of the new problem, our friend CA2000 "Dispose objects before losing scope" ... so at this point I just face palmed for a minute. Did a few Google searches, and found this post. That's when it dawned on me, to pass for both CA rules, you need to ensure everything is disposed once and only once for all code branches. So I set out to do this, which isn't a hard problem once you realize this is what you need to do.
Naturally, the code evolved to this:
MemoryStream msDecrypt = null;
CryptoStream csDecrypt = null;
try
{
msDecrypt = new MemoryStream();
csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write);
csDecrypt.Write(eop.m_Ciphertext, 0, eop.m_Ciphertext.Length);
csDecrypt.FlushFinalBlock();
decrypted = msDecrypt.ToArray();
}
finally
{
if (csDecrypt != null)
{
csDecrypt.Dispose();
}
else if (msDecrypt != null)
{
msDecrypt.Dispose();
}
}
Finally, I had code that didn't result in a CA2000 or CA2202. The moral of the story is that the USING statement, is a lot less valuable than it was in the past now that code analysis rules have evolved in this way.
There are a few different ways you can write the code to make this work, I just chose a way that doesn't mix explicit calls to dispose with using statements, because I believe this to be simpler to read as well as structured in a way that would prevent someone from just going and wrapping another using around it, resulting in the originally issue unknowingly.
If you dispose the StreamReader, you are also disposing the underlying stream.
If you comment out objStream.Dispose() then you run into the chance of something throwing an exception before you even get to the nested try block - which will result in your stream not getting disposed.
There's a nice explanation here:
Does disposing streamreader close the stream?
This is not the answer, but you might find this code more readable:
public String ToXml()
{
var objSerializer =
new DataContractSerializer(GetType());
using (var objStream = new MemoryStream())
{
// Serialize the object
objSerializer.WriteObject(objStream, this);
// Move to start of stream to read
// out contents
objStream.Seek(0, SeekOrigin.Begin);
using (var objReader =
new StreamReader(objStream))
{
// Read Contents into a string
retirm objReader.ReadToEnd();
}
}
}
If you came across some C# code like this with nested using statements/resources:
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var reader = new BinaryReader(responseStream))
{
// do something with reader
}
}
}
Is it safe to replace it with something like this?
using (var reader = new BinaryReader(((HttpWebResponse)request.GetResponse()).GetResponseStream()))
{
// do something with reader
}
The example above is just an example of nested disposable resources, so forgive me if it's not exactly correct usage. I'm curious if when you dispose the outermost resource (the BinaryReader in this case), if it will recursively dispose its children for you, or if you need to explicitly dispose each "layer" with separate using statements? E.g. if you dispose the BinaryReader, is it supposed to dispose the response stream, which in turn disposes the response? Thinking about that last sentence makes me think you actually do need the separate using statements, because there's no way to guarantee that a wrapper object would dispose of the inner object. Is that right?
You should just stack your using statements - it has the desired effect you are looking for:
using (var response = (HttpWebResponse)request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new BinaryReader(responseStream))
{
// do something with reader
}
You need the separate using statements.
In your second example, only the BinaryReader will get disposed, not the objects used to construct it.
In order to see why, look at what the using statement actually does. It takes your second code, and does something equivalent to:
{
var reader = new BinaryReader(((HttpWebResponse)request.GetResponse()).GetResponseStream());
try
{
// do something with reader
}
finally
{
if (reader != null)
((IDisposable)reader).Dispose();
}
}
As you can see, there would never be a Dispose() call on the Response or ResponseStream.
FWIW, here's another way to spell your original example which may satisfy any dismay over nesting:
using (var response = (HttpWebResponse)request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new BinaryReader(responseStream))
{
// do something with reader
}
Whether the reader disposes of the stream is really a function of the reader, not the 'using'. As I recall that is often what the behavior with readers is--they take ownership of the stream and dispose of it when the reader is itself closed. But the form I've provided above should be fine.
According to the documentation, BinaryReader.Close will close the underlying stream. http://msdn.microsoft.com/en-us/library/system.io.binaryreader.close.aspx
Also, according to the documentation for HttpWebResponse, you either have to close the underlying stream or dispose the response. http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx
So the second example you provided would work.
I posted this elsewhere, but separating your declarations by comma seems to treat each statement separated this way as a new declaration and disposes of them.
using (IType1 a = new Type1(), b = new Type1()){}
This however means your objects must be of the same type. You could call them like
using (IDisposable a = new Type1(), b = new Type2()){}
But then of course, you only have access to IDisposable methods, without casting the object, which is kinda dumb. So instead, I believe you can use
using (var a = new Type1(), b = new Type2()){}
This appears to give you the correctly typed object references allowing you access to the proper method of the allocated type, and disposes of both objects created. If anyone knows why I'm not right, please let me know because this appears to work for me? (I know this question is really old n stuff, but it's all I could find while searching for this answer myself)
I have lots of code like this:
FileStream fs = File.Open(#"C:\Temp\SNB-RSS.xml", FileMode.Open);
using (XmlTextReader reader = new XmlTextReader(fs))
{
/* Some other code */
}
This gives me the following Code Analysis warning:
CA2000 : Microsoft.Reliability : In method 'SF_Tester.Run()', object 'fs' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'fs' before all references to it are out of scope.
If I follow the suggestion and I put the File.Open in a using statement, I get this:
CA2202 : Microsoft.Usage : Object 'fs' can be disposed more than once in method 'SF_Tester.Run()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 39
I'm using VS2010 and I can't help but think I'm doing something wrong but I don't see it.
What am I doing wrong?
Sigh, exhausting isn't it. Avoid all this by using the recommended Create() method:
using (var reader = XmlReader.Create(#"C:\Temp\SNB-RSS.xml")) {
//...
}
As nobody provided a solution that solves this issue yet, I'm writing my working solution down here:
FileStream fs = new FileStream(fileName, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite);
try
{
using (var fileWriter = new StreamWriter(fs, encoding))
{
fs = null;
fileWriter.Write(content);
}
}
finally
{
if (fs != null)
fs.Dispose();
}
This removes CA2000.
I am only guessing; don't have time to go through a full analysis now.
Suppose the XmlTextReader constructor 'takes ownership' of the stream passed in, and so disposing the XmlTextReader will also Dispose the underlying stream. That would explain the behavior you see. Perhaps XmlTextReader constructor can throw, and in that instance, the original warning about fs would make sense. However, given that hypothesis, this code
var fs = File.Open(#"C:\Temp\SNB-RSS.xml", FileMode.Open);
XmlTextReader reader = null;
try
{
reader = new XmlTextReader(fs);
}
finally
{
if (reader== null)
{
fs.Dispose();
}
}
if (reader != null)
{
using (reader)
{
/* Some other code */
}
}
is, I think, correct, but still yields a spurious warning. This smells like a nice example that demonstrates the limitations of static analysis tools.
As someone else said, there is another API to directly create the reader from the filename (XmlReader.Create()), which avoids all this (and shows how well-designed scenario-focused APIs are a good thing for a surprising variety of reasons).
It's a known issue
http://connect.microsoft.com/VisualStudio/feedback/details/535118/ca2000-and-ca2202-offer-contradictory-warnings
If you're using a StreamWriter rather than XmlTextReader (as in the solution above) you could use a similar method via the relevant constructor; e.g.
var sw = new StreamWriter("filename.txt");
or
var sw = new StreamWriter("filename.txt", /*append to file = */ false );
It is not clear from the documentation whether the first form of constructor will overwrite or append to a file.
As mentioned in this answer, the only way to work around it correctly is to do as recommended in CA2202 and use an outer try-finally block instead of an outer using block. Inside the inner using, set the outer IDisposable object to null to prevent it from being accessed once the inner using has finished.
Here's a generic wrapper that does it "correctly", i.e. works around the badly designed XmlReader (maybe it should not have taken ownership of the stream it receives? Not sure what the right way to do it would be)
Disclaimer: Not really tested
public static TResult SafeNestedUsing<TOuter, TInner, TResult>(Func<TOuter> createOuterDisposable, Func<TOuter, TInner> createInnerDisposable, Func<TInner, TResult> body)
where TInner : IDisposable
where TOuter : class, IDisposable
{
TOuter outer = null;
try
{
outer = createOuterDisposable();
using (var inner = createInnerDisposable(outer))
{
var result = body(inner);
outer = null;
return result;
}
}
finally
{
if (null != outer)
{
outer.Dispose();
}
}
}
Example usage:
SafeNestedUsing<MemoryStream, XmlReader, XmlDocument>(
() => new MemoryStream(array),
(memStream) => XmlReader.Create(memStream, xmlReaderSettings),
(xmlReader) =>
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
return xmlDoc;
});
This is quite clunky, and you may argue that it's better to repeat the try/set null/finally pattern instead. But for a repeating pattern of nested usings I'd rather do it this way than repeat the full thing each time.
just use 'using' for the filestream
using(FileStream fs = new FileStream(fileName, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
// some codes here
}
Don't modify fs and don't use fs.close() inside using curly braces.
Use the using statement also on the FileStream itself just like on the XmlTextReader.
http://msdn.microsoft.com/en-us/library/system.io.filestream(VS.71).aspx.
Grz, Kris.
I've got a third-party component that does PDF file manipulation. Whenever I need to perform operations I retrieve the PDF documents from a document store (database, SharePoint, filesystem, etc.). To make things a little consistent I pass the PDF documents around as a byte[].
This 3rd party component expects a MemoryStream[] (MemoryStream array) as a parameter to one of the main methods I need to use.
I am trying to wrap this functionality in my own component so that I can use this functionality for a number of areas within my application. I have come up with essentially the following:
public class PdfDocumentManipulator : IDisposable
{
List<MemoryStream> pdfDocumentStreams = new List<MemoryStream>();
public void AddFileToManipulate(byte[] pdfDocument)
{
using (MemoryStream stream = new MemoryStream(pdfDocument))
{
pdfDocumentStreams.Add(stream);
}
}
public byte[] ManipulatePdfDocuments()
{
byte[] outputBytes = null;
using (MemoryStream outputStream = new MemoryStream())
{
ThirdPartyComponent component = new ThirdPartyComponent();
component.Manipuate(this.pdfDocumentStreams.ToArray(), outputStream);
//move to begining
outputStream.Seek(0, SeekOrigin.Begin);
//convert the memory stream to a byte array
outputBytes = outputStream.ToArray();
}
return outputBytes;
}
#region IDisposable Members
public void Dispose()
{
for (int i = this.pdfDocumentStreams.Count - 1; i >= 0; i--)
{
MemoryStream stream = this.pdfDocumentStreams[i];
this.pdfDocumentStreams.RemoveAt(i);
stream.Dispose();
}
}
#endregion
}
The calling code to my "wrapper" looks like this:
byte[] manipulatedResult = null;
using (PdfDocumentManipulator manipulator = new PdfDocumentManipulator())
{
manipulator.AddFileToManipulate(file1bytes);
manipulator.AddFileToManipulate(file2bytes);
manipulatedResult = manipulator.Manipulate();
}
A few questions about the above:
Is the using clause in the AddFileToManipulate() method redundant and unnecessary?
Am I cleaning up things OK in my object's Dispose() method?
Is this an "acceptable" usage of MemoryStream? I am not anticipating very many files in memory at once...Likely 1-10 total PDF pages, each page about 200KB. App designed to run on server supporting an ASP.NET site.
Any comments/suggestions?
Thanks for the code review :)
AddFileToManipulate scares me.
public void AddFileToManipulate(byte[] pdfDocument)
{
using (MemoryStream stream = new MemoryStream(pdfDocument))
{
pdfDocumentStreams.Add(stream);
}
}
This code is adding a disposed stream to your pdfDocumentStream list. Instead you should simply add the stream using:
pdfDocumentStreams.Add(new MemoryStream(pdfDocument));
And dispose of it in the Dispose method.
Also you should look at implementing a finalizer to ensure stuff gets disposed in case someone forgets to dispose the top level object.
Is the using clause in the AddFileToManipulate() method redundant and unnecessary?
Worse, it's destructive. You're basically closing your memory stream before it's added in. See the other answers for details, but basically, dispose at the end, but not any other time. Every using with an object causes a Dispose to happen at the end of the block, even if the object is "passed off" to other objects via methods.
Am I cleaning up things OK in my object's Dispose() method?
Yes, but you're making life more difficult than it needs to be. Try this:
foreach (var stream in this.pdfDocumentStreams)
{
stream.Dispose();
}
this.pdfDocumentStreams.Clear();
This works just as well, and is much simpler. Disposing an object does not delete it - it just tells it to free it's internal, unmanaged resources. Calling dispose on an object in this way is fine - the object stays uncollected, in the collection. You can do this and then clear the list in one shot.
Is this an "acceptable" usage of MemoryStream? I am not anticipating very many files in memory at once...Likely 1-10 total PDF pages, each page about 200KB. App designed to run on server supporting an ASP.NET site.
This depends on your situation. Only you can determine whether the overhead of having these files in memory is going to cause you problems. This is going to be a fairly heavy-weight object, though, so I'd use it carefully.
Any comments/suggestions?
Implement a finalizer. It's a good idea whenever you implement IDisposable. Also, you should rework your Dispose implementation to the standard one, or mark your class as sealed. For details on how this should be done, see this article. In particular, you should have a method declared as protected virtual void Dispose(bool disposing) that your Dispose method and your finalizer both call.
It looks to me like you misunderstand what Using does.
It's just syntactic sugar to replace
MemoryStream ms;
try
{
ms = new MemoryStream();
}
finally
{
ms.Dispose();
}
Your usage in AddFileToManipulate is redundant. I'd set up the list of memorystreams in the constructor of PdfDocumentManipulator, then have PdfDocumentManipulator's dispose method call dispose on all the memorystreams.
Side note. This really seems like it calls for an extension method.
public static void DisposeAll<T>(this IEnumerable<T> enumerable)
where T : IDisposable {
foreach ( var cur in enumerable ) {
cur.Dispose();
}
}
Now your Dispose method becomes
public void Dispose() {
pdfDocumentStreams.Reverse().DisposeAll();
pdfDocumentStreams.Clear();
}
EDIT
You don't need the 3.5 framework in order to have extension methods. They will happily work on the 3.0 compiler down targeted to 2.0
http://blogs.msdn.com/jaredpar/archive/2007/11/16/extension-methods-without-3-5-framework.aspx