how to dispose of a streamwriter without closing the underlyingstream

A

ajfish

Hi,

I have a function func(Stream s) which uses a StreamWriter to write to
the Stream.

It is imperative that the stream remain open after the function has
returned. However, It seems that Close()ing or Dispose()ing a
StreamWriter automatically closes the underlying stream by design.

So is it OK for me to just flush the StreamWriter in the finally
clause of func and never dispose of it ?

I found a post (see below) but it's pretty old so I wondered whether
it is correct and if anything has changed?

http://groups.google.com/group/microsoft.public.dotnet.framework/browse_frm/thread/80e15ad9afd4fff6

Andy
 
J

Jeff Johnson

I have a function func(Stream s) which uses a StreamWriter to write to
the Stream.

It is imperative that the stream remain open after the function has
returned. However, It seems that Close()ing or Dispose()ing a
StreamWriter automatically closes the underlying stream by design.

So is it OK for me to just flush the StreamWriter in the finally
clause of func and never dispose of it ?

I found a post (see below) but it's pretty old so I wondered whether
it is correct and if anything has changed?

http://groups.google.com/group/microsoft.public.dotnet.framework/browse_frm/thread/80e15ad9afd4fff6

I looked at the code through Reflector. The Dispose() method will close the
stream if it's called with a parameter of true, but not if called with
false. Close() calls it with true. So if you can somehow force disposal
without going through Close() you should be able to keep your stream alive.
 
A

Alberto Poblacion

So is it OK for me to just flush the StreamWriter in the finally
clause of func and never dispose of it ?

This is going to give you trouble. After the StreamWriter becomes
unreachable, it is made available to the Garbage Collector. Whenever the GC
decides that it needs to collect memory, it will see that the StreamWriter
has a Finalizer that has not been Suppressed, and move it to the
Finalization Queue. When the thread that processes the finalization Queue
gets to the Finalizer of your StreamWriter, it will be processed and it will
in turn call Dispose(). This means that your Stream will be randomly Closed
at some arbitrary time in the future, which will cause your program to fail
intermittently for no apparent reason. For simple Windows programs, most of
the time this will not happen until the program is closed, so it will appear
to work correctly during testing. However, it may later fail in production
in non-reproducible ways, which are a nightmare to debug.
 
A

ajfish

    This is going to give you trouble. After the StreamWriter becomes
unreachable, it is made available to the Garbage Collector. Whenever the GC
decides that it needs to collect memory, it will see that the StreamWriter
has a Finalizer that has not been Suppressed, and move it to the
Finalization Queue. When the thread that processes the finalization Queue
gets to the Finalizer of your StreamWriter, it will be processed and it will
in turn call Dispose(). This means that your Stream will be randomly Closed
at some arbitrary time in the future, which will cause your program to fail
intermittently for no apparent reason. For simple Windows programs, most of
the time this will not happen until the program is closed, so it will appear
to work correctly during testing. However, it may later fail in production
in non-reproducible ways, which are a nightmare to debug.

thanks for this comment - i was worried something like this could
happen which is why i thought it worth asking.

it seems to me that what I am asking for is something which is quite a
common and reasonable requirement i.e. to be able to write a utility
function which appends something to a stream without closing, and to
implement that function using a StreamWriter

short of subclassing StreamWriter to not close the stream on dispose,
is there any better way of achieving what i want to achieve?
 
P

Peter Morris

I don't recall exactly how I solved this, but it was something like

public class NonClosingStream : Stream
{
readonly Stream InnerStream;

public NonClosingStream(Stream innerStream)
{
//check not null
InnerStream = innerStream;
}

//override each method and pass it on to innerStream

public bool CanClose { get; set; }

public override Close()
{
if (CanClose)
base();
}
}


Then you can do this

using (var myStream = new FileStream(.....))
{
var nonClosingStream = new NonClosingStream(myStream);
using (var writer = new StreamWriter(nonClosingStream))
{
}
using (var writer = new StreamWriter(nonClosingStream))
{
}
nonClosingStream.CanClose = true;
using (var writer = new StreamWriter(nonClosingStream))
{
}
}

The only thing is, doesn't StreamWriter write some kind of preamble into the
stream so that encoding can be determined?
 
J

Jeroen Mostert

I have a function func(Stream s) which uses a StreamWriter to write to
the Stream.

It is imperative that the stream remain open after the function has
returned. However, It seems that Close()ing or Dispose()ing a
StreamWriter automatically closes the underlying stream by design.

So is it OK for me to just flush the StreamWriter in the finally
clause of func and never dispose of it ?
No. You can't control when the instance is disposed, unless you make
artificially make sure that the StreamWriter never, ever becomes
unreachable. This is harder than it sounds. You may find a solution that
works in practice, but not in theory, and is subject to breaking with every
new release of the framework.

Peter linked you to another thread, which also happens to contain the
simplest solution for cases like this (assuming a single encoding, and not
using multiple StreamWriters at the same time): wrap the stream in a special
Stream class that ignores attempts to close it (and instead just calls
..Flush()) for purposes of passing to the StreamWriter.

Another, less hackish solution is to not use a StreamWriter at all, and
instead use Encoding and Stream.Write() directly.
 
J

Jeroen Mostert

Peter Morris wrote:
The only thing is, doesn't StreamWriter write some kind of preamble into
the stream so that encoding can be determined?
Not by default. If you explicitly pass it an Encoding, though, it will (but
this only really matters for the Unicode encodings).
 
A

ajfish

Peter linked you to another thread, which also happens to contain the
simplest solution for cases like this (assuming a single encoding, and not
using multiple StreamWriters at the same time): wrap the stream in a special
Stream class that ignores attempts to close it (and instead just calls
.Flush()) for purposes of passing to the StreamWriter.

Another, less hackish solution is to not use a StreamWriter at all, and
instead use Encoding and Stream.Write() directly.

Thanks for all the responses. I think peter's solution is a good way
to go. I'm just curious as to why MS couldn't have put some kind of
property on the StreamWriter to affect whether it closes the
underlying stream.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top