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

时间:2011-07-08 16:02:00

标签: .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;
}

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

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

2 个答案:

答案 0 :(得分:6)

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

  

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

     

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

     

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

     

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

答案 1 :(得分:0)

我向Microsoft提交了一个针对此问题的错误报告:Catastrophic Failure exception thrown after loading too many BitmapImage objects from a Stream

现在,我将尝试使用较小的图像文件作为缩略图和/或不加载如此多的BitmapImages(当它们不在可视区域时卸载图像并在它们到来时重新加载它们)进入视图)。