Memorystream.Close() or Memorystream.Dispose()

MemoryStream.Close() or MemoryStream.Dispose()

Close() and Dispose(), when called on a MemoryStream, only serve to do two things:

  • Mark the object disposed so that future accidental usage of the object will throw an exception.
  • Possibly1 release references to managed objects, which can make the GC's job a bit easier depending on the GC implementation. (On today's GC algorithms it makes no real difference, so this is a point for an academic discussion and has no significant real-world impact.)

MemoryStream does not have any unmanaged resources to dispose, so you don't technically have to dispose of it. The effect of not disposing a MemoryStream is roughly the same thing as dropping a reference to a byte[] -- the GC will clean both up the same way.

Which one do I call? Is it necessary to call both?

The Dispose() method of streams delegate directly to the Close() method2, so both do exactly the same thing.

Will the other throw an exception if I have already called one of them?

The documentation for IDisposable.Dispose() specifically states it is safe to call Dispose() multiple times, on any object3. (If that is not true for a particular class then that class implements the IDisposable interface in a way that violates its contract, and this would be a bug.)

All that to say: it really doesn't make a huge difference whether you dispose a MemoryStream or not. The only real reason it has Close/Dispose methods is because it inherits from Stream, which requires those methods as part of its contract to support streams that do have unmanaged resources (such as file or socket descriptors).


1 Mono's implementation does not release the byte[] reference. I don't know if the Microsoft implementation does.

2 "This method calls Close, which then calls Stream.Dispose(Boolean)."

3 "If an object's Dispose method is called more than once, the object must ignore all calls after the first one."

Do I need to close this memory stream?

Since the memory stream is encapsulated in the return value, you should not dispose it. If you do, it will be disposed before the FileStreamResult can access it.

The stream is already disposed inside the FileStreamResultExecutor.ExecuteAsync method, as you can see in the source.

The same is true for ASP.NET MVC, where is it FileStreamResult.WriteFile that does the disposal (source).

Is a memory leak created if a MemoryStream in .NET is not closed?

If something is Disposable, you should always Dispose it. You should be using a using statement in your bar() method to make sure ms2 gets Disposed.

It will eventually get cleaned up by the garbage collector, but it is always good practice to call Dispose. If you run FxCop on your code, it would flag it as a warning.

How to dispose of a MemoryStream object

using blocks are not much more than syntactic sugar for try-finally blocks.

Depending on how the using block is used, you end up with two types of try-finally blocks.

Case 1:

// This code ...
using( var thing = new Thing() ) {
thing.DoOperation();
}

// ... turns into this scoped try-finally:
{
var thing = new Thing();
try {
thing.DoOperation();
}
finally {
thing.Dispose();
thing = null;
}
}

Case two:

// This code ...
var thing = new Thing();
using( thing ) {
thing.DoOperation();
}

// ... turns into this code
var thing = new Thing();
try {
thing.DoOperation();
}
finally {
thing.Dispose();
// Note the lack of a null assignment.
}

With this knowledge, you can modify your third solution to use a finally block to ensure that your MemoryStream objects are always cleaned up.

PDFUtility.Document docFinal = new PDFUtility.Document();
PDFUtility.Document docToAdd = byte[] combinedFile;
List<MemoryStream> streams = new List<MemoryStream>();

try
{
foreach (byte[] content in fileContents)
{
MemoryStream fileContentStream = new MemoryStream(content);
streams.Add(fileContentStream); //EACH INSTANCE OF A STREAM IS TRACKED
docToAdd = new PDFUtility.Document(fileContentStream);
docFinal.Pages.AddRange(docToAdd.Pages.CloneToArray());
}
using (MemoryStream stream = new MemoryStream())
{
docFinal.Write(stream);
combinedFile = stream.ToArray();
}

}
finally
{
streams.ForEach(s => s.Dispose()); //DISPOSE OF ALL STREAMS HERE
}

Does a memorystream get disposed when returning from within a using block

The code may work because Dispose on a MemoryStream doesn't really do anything (the memory is reclaimed by GC), but I certainly wouldn't depend on it always doing so for all .NET implementations - unless the only function you're calling is GetBuffer(), which is guaranteed to work after closing the stream. It's probably safer to remove the 'using' in this case.
The "read-only" refers to the inability to re-assign the reference to another object.
BTW if you look at https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/MemoryStream.cs the comments in Dispose() indicate that the developers deliberately intended for the object buffer to still available after disposing, but there's no guarantee reading from it as a stream will work (and writing will almost certainly fail).

MemoryStream in Using Statement - Do I need to call close()

No, it's not.

using ensures that Dispose() will be called, which in turn calls the Close() method.

You can assume that all kinds of Streams are getting closed by the using statement.

From MSDN:

When you use an object that accesses unmanaged resources, such as a StreamWriter, a good practice is to create the instance with a using statement. The using statement automatically closes the stream and calls Dispose on the object when the code that is using it has completed.

Should I call Close() or Dispose() for stream objects?

A quick jump into Reflector.NET shows that the Close() method on StreamWriter is:

public override void Close()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

And StreamReader is:

public override void Close()
{
this.Dispose(true);
}

The Dispose(bool disposing) override in StreamReader is:

protected override void Dispose(bool disposing)
{
try
{
if ((this.Closable && disposing) && (this.stream != null))
{
this.stream.Close();
}
}
finally
{
if (this.Closable && (this.stream != null))
{
this.stream = null;
/* deleted for brevity */
base.Dispose(disposing);
}
}
}

The StreamWriter method is similar.

So, reading the code it is clear that that you can call Close() & Dispose() on streams as often as you like and in any order. It won't change the behaviour in any way.

So it comes down to whether or not it is more readable to use Dispose(), Close() and/or using ( ... ) { ... }.

My personal preference is that using ( ... ) { ... } should always be used when possible as it helps you to "not run with scissors".

But, while this helps correctness, it does reduce readability. In C# we already have plethora of closing curly braces so how do we know which one actually performs the close on the stream?

So I think it is best to do this:

using (var stream = ...)
{
/* code */

stream.Close();
}

It doesn't affect the behaviour of the code, but it does aid readability.

Call to MemoryStream.GetBuffer() succeeds even after MemoryStream.Close(); Why?

  1. It doesn't need to. The buffer is managed memory, so normal garbage collection will deal with it, without needing to be included in the disposal.
  2. It's useful to be able to get the bytes of the memory stream, even after the stream has been closed (which may have happened automatically after the steam was passed to a method that writes something to a stream and then closes said stream). And for that to work, the object needs to hold onto the buffer along with a record of how much had been written to it.

In considering the second point, it actually makes more sense in a lot of cases to call ToArray() (which as said, requires the in-memory store that GetBuffer() returns to still be alive) after you've closed the stream, because having closed the stream guarantees that any further attempt to write to the stream will fail. Hence if you have a bug where you obtain the array too early, it will throw an exception rather than just give you incorrect data. (Obviously if you explicitly want to get the current array part-way through the stream operations, that's another matter). It also guarantees that all streams are fully flushed rather than having part of their data in a temporary buffer (MemoryStream isn't buffered because MemoryStream essentially is a buffer, but you may have been using it with chained streams or writers that had their own separate buffer).



Related Topics



Leave a reply



Submit