Wednesday, June 29, 2011

Coconut

Simple, but little painful snare regarding Streams and StreamWriters.

Let's imagine we have a function that print some data to a TextWriter:

void Print(TextWriter writer)
{
 // ...
}

Also we have a stream (e.g. Http output stream), which we want to use to print in data. So, we'll write something like:

using (Stream stream = GetOutputStream()){
  var streamWriter = new StreamWriter(stream);
  Print(streamWriter);
}

This code is fair enough - as far as StreamWriter uses the disposed stream, there should not be any resource leaks as far as we're disposing the thread. But there is some bug which can lead to data losses.



StreamWriter is not so simple as we've thought. It does not 'stream' data directly - it uses some internal buffer and StreamWriter flush its data to the nested stream when the buffer is full or when StreamWriter.Dispose() is called.

In our case the last chunk of data will be lost because the buffer will never be flushed to the stream.

The correct code is:

using (StreamWriter streamWriter = new StreamWriter(GetOutputStream())){
  Print(streamWriter);
}

The StreamWriter will also dispose the provided stream in StreamWriter.Dispose(), so there is no resource leaks as well.

No comments:

Post a Comment