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

2023-09-02 10:52:02 作者:巴黎左岸的小镇

我需要动态加载缩略图许多(有时是几百个)。因为我需要做到这一点的请求数量有限性能方面的原因,我使用的是单一的请求/响应进行测试。我送二进​​制数据为在响应中的图像并装入的BitmapImage的使用一个MemoryStream。这正常工作,直到我装入超过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作为页面上的图像元素的来源,但发生在 img.SetSource(...)行上述错误。

添加 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.

推荐答案

我想引用答案在上面的bug报告提供由微软是值得的,因为它是非常简洁的描述性的问题,以及提供建议的解决方案:

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中加载一个图像,该框架有一个参考和缓存德codeD映像,直到流控制返回到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.

我理解当前日code行为,它并不明显,Silverlight是留住这些引用,但改变德codeR设计可能会影响其他地区,所以现在我建议这样的处理图像的批次。

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.

现在,如果你实际上是试图加载5​​00张图片,并留住他们,你仍然可能耗尽内存取决于图像大小。如果您正在处理多页文档,可能要改为按需加载页面的背景和外出时的观点与缓冲区的几页,以便在任何时候你超过合理的纹理内存限制释放他们。

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.