Silverlight:来自流的BitmapImage抛出异常(灾难性故障(HRESULT异常:0x8000FFFF(E_UNEXPECTED)))

tob*_*oby 7 .net silverlight bitmapimage

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

下面是从字节数组加载图像的示例,已知字节数组具有有效的图像数据(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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

Xca*_*bur 6

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

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

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

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

现在,如果您实际上正在尝试加载500张图像并保留它们,则根据图像大小,您仍可能会耗尽内存.如果您正在处理多页文档,您可能希望在后台按需加载页面,并在具有几页缓冲区的视图之外释放它们,这样您就不会超出合理的纹理内存限制.