views:

938

answers:

2

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!

+2  A: 

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)
    } 
}
Marc Gravell
thanks! both good answers, i just marked the one that came first :)i like the host/bucket reference.
moogs
@moogs - actually this one came in first (04:55:29 vs 04:46:05).
Alconja
that was weird... the "answered xx mins ago" was higher for this post earlier. hmm.
moogs
I assure you that even with ♦ I can't change that.
Marc Gravell
+4  A: 

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.

Ben M