开发者

Silverlight: BitmapImage from stream throws exception (Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)))

I need to dynamically load many (sometimes hundreds) of thumbnail images. For performance reasons I need to do this in a limited number of requests, I am using a single request/response for testing. I am sending the binary data for the images in the response and loading them into BitmapImage's using a MemoryStream. This works correctly until I load more than about 80 thumbnails, then I get the Catastrophic Failure exception. To make sure my data was not corrupt I tried loading a BitmapImage multiple times with the same byte array and it crashes after 80 or so loads.

Here is a sample of how the image is loaded from the byte array, the byte array is known to have valid image data (png):

private BitmapImage LoadImage(byte[] imageData)
{
    BitmapImage img = new BitmapImage();
    MemoryStream stream = new MemoryStream(imageData);
    img.SetSource(s开发者_Go百科tream); // Exception thrown here after too many images loaded.
    return img;
}

I then use the BitmapImage as a source for an Image element on the page, but the error occurs in the img.SetSource(...) line above.

Adding GC.Collect() to the loop where I am loading thumbnail images lets me load a few more images, so I'm thinking this has something to do with memory management but I don't know what I can do to fix the problem.


I think quoting the answer providing by Microsoft in the above bug report is worthwhile since it is very succinct and descriptive of the problem as well as providing a recommended solution:

When Silverlight loads an image, the framework keeps a reference and caches the decoded image until flow control is returned to the UI thread dispatcher. When you load images in a tight loop like that, even though your application doesn't retain a reference, the GC can't free the image until we release our reference when flow control is returned.

After processing 20 or so images, you could stop and queue the next set using Dispatcher.BeginInvoke just to break up the work that is processed in one batch. This will allow us to free images that aren't retained by your application.

I understand with the current decode behavior it's not obvious that Silverlight is retaining these references, but changing the decoder design could impact other areas, so for now I recommend processing images like this in batches.

Now, if you're actually trying to load 500 images and retain them, you are still likely to run out of memory depending on image size. If you're dealing with a multi-page document, you may want to instead load pages on demand in the background and release them when out of view with a few pages of buffer so that at no point do you exceed reasonable texture memory limits.


I submitted a bug report with Microsoft for this issue: Catastrophic Failure exception thrown after loading too many BitmapImage objects from a Stream.

For now, I'm going to try working around this by using smaller image files for the thumbnails and/or not loading so many BitmapImages (unloading images when they are not in the viewable area and re-loading them when they come into view).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜