Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot Access Closed Stream

I'm trying to use the Caching Application Block to cache some images (these images take a long time to render)

  BitmapSource bitmapSource; ///some bitmap source already created
  _cache ///  Caching Application Block
  String someId; //id for this image, used as the key for the cache

  using (var stream = new MemoryStream())
    {
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Interlace = PngInterlaceOption.On;
        encoder.Frames.Add(BitmapFrame.Create(bitmapSource));             
        encoder.Save(stream);
        _cache.Add(someId, stream);
    }

And then load them using:

imStream = (Stream)_cache.GetData(someId));
if (imStream != null)
{
    PngBitmapDecoder decoder = new PngBitmapDecoder(imStream,  BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    return decoder.Frames[0];  //return the bitmap source
}

But during the load, i get the following exception at that "new PngBitmapDecoder" line:

"Cannot access a closed Stream.

I understand I closed the stream in the above code, but isn't _cache.Add() making a copy (via Serialization) before it exits? What's the correct process of serializing the stream?

THanks!

like image 803
moogs Avatar asked Feb 25 '10 04:02

moogs


2 Answers

The problem is that the stream is closed (via Dispose()) at the end of the using block. You retain a reference to the closed stream.

Instead, save the contents of the stream to your cache:

_cache.Add(someId, stream.ToArray());

When you call the PngBitmapDecoder constructor, you'll have to create a new MemoryStream to read from that byte array.

like image 102
Ben M Avatar answered Sep 21 '22 11:09

Ben M


but isn't _cache.Add() making a copy (via Serialization) before it exits?

Not necessarily. If it is "in process" it will just store the object reference; Stream isn't really very serializable anyway (a Stream is a hose, not a bucket).

You want to store the BLOB - not the Stream:

    _cache.Add(someId, stream.ToArray());

...

byte[] blob = _cache.GetData(someId);
if(blob != null) {
    using(Stream inStream = new MemoryStream(blob)) {
         // (read)
    } 
}
like image 39
Marc Gravell Avatar answered Sep 19 '22 11:09

Marc Gravell