Silverlight:来自流的 BitmapImage 引发异常(灾难性故障(来自 HRESULT 的异常:0x8000FFFF (E_UNEXPECTED))) [英] Silverlight: BitmapImage from stream throws exception (Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)))

查看:16
本文介绍了Silverlight:来自流的 BitmapImage 引发异常(灾难性故障(来自 HRESULT 的异常:0x8000FFFF (E_UNEXPECTED)))的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要动态加载许多(有时是数百个)缩略图.出于性能原因,我需要在有限数量的请求中执行此操作,我使用单个请求/响应进行测试.我正在发送响应中图像的二进制数据,并使用 MemoryStream 将它们加载到 BitmapImage 中.这可以正常工作,直到我加载了大约 80 个缩略图,然后我收到了灾难性故障异常.为了确保我的数据没有损坏,我尝试使用相同的字节数组多次加载 BitmapImage,但它在加载 80 次左右后崩溃.

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.

以下是如何从字节数组加载图像的示例,已知字节数组具有有效的图像数据 (png):

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(stream); // Exception thrown here after too many images loaded.
    return img;
}

然后我使用 BitmapImage 作为页面上 Image 元素的源,但错误发生在上面的 img.SetSource(...) 行中.

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.

在我加载缩略图的循环中添加 GC.Collect() 可以让我加载更多的图像,所以我认为这与内存管理有关,但我没有我不知道我能做些什么来解决这个问题.

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.

推荐答案

我认为在上述错误报告中引用 Microsoft 提供的答案是值得的,因为它非常简洁和描述了问题,并提供了推荐的解决方案:

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:

当 Silverlight 加载图像时,框架会保留一个引用并缓存解码后的图像,直到流控制返回到 UI 线程调度程序.当您以这样的紧密循环加载图像时,即使您的应用程序没有保留引用,GC 也无法释放图像,直到我们在返回流控制时释放引用.

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.

处理完 20 个左右的图像后,您可以使用 Dispatcher.BeginInvoke 停止并排队下一组,只是为了分解一批处理的工作.这将使我们能够释放您的应用程序未保留的图像.

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.

我理解根据当前的解码行为,Silverlight 保留这些引用并不明显,但更改解码器设计可能会影响其他领域,因此现在我建议分批处理这样的图像.

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.

现在,如果您实际上尝试加载 500 个图像并保留它们,根据图像大小,您仍然可能会耗尽内存.如果您正在处理多页文档,您可能希望在后台按需加载页面,并在有几页缓冲区的情况下在视野之外释放它们,以便在任何时候都不会超出合理的纹理内存限制.

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.

这篇关于Silverlight:来自流的 BitmapImage 引发异常(灾难性故障(来自 HRESULT 的异常:0x8000FFFF (E_UNEXPECTED)))的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆