4

我在 .net 应用程序中为我的 ListView 使用 ImageList 时遇到了一些问题。在我的实现中,这个 ImageList 可以根据使用情况保存几千张图像。这个问题最初是在我尝试处理大量图像时出现的。一旦超过 5K+ 图像,我在尝试添加图像时遇到了一个通用的“图像无法添加到 ImageList”异常。发生此故障的确切数字略有跳跃。

因此,在尝试解决此问题时,我尝试使用本机 ImageList_SetImageCount 函数扩展 ImageList 的容量。这很好,解决了我眼前的问题。我必须使用 ImageList[index] = image 而不是 .Add() 方法填充列表。这一切都很好,但是当需要拉出图像时,问题就出现了。现在,每当我通过索引引用该 ImageList 中的图像时,我都会收到内存不足异常。Bitmap x = ImageList[any index] 会崩溃。

我尝试过很多不同的方法,但仍然遇到 ImageList 的问题。

在我最后一次尝试进一步探索这个问题时,我整理了以下仍然表现奇怪的测试代码!

    private void Form1_Load(object sender, EventArgs e)
    {
        list = new ImageList();
        list.ImageSize = new Size(128, 128);
        list.ColorDepth = ColorDepth.Depth32Bit;
        Image[] images = new Image[10];
        for (int y = 0; y < 10; y++)
        {
            images[y] = new Bitmap(@"Path to loading_photo.png");
        }
        for (int x = 0; x < 750; x++)
        {
            list.Images.AddRange(images);
        }

        list.Images[12] = new Bitmap(@"Path to another.png");

最后一行因“无法将图像添加到 ImageList”错误而崩溃。奇怪的是,将第二个循环设置为较低的迭代次数(即添加 2000 张图像时为 200 次),它的表现还不错。

我不知道.net 中的 ImageList 是否有一定的阈值?任何帮助将不胜感激。

4

2 回答 2

3

对于发布的代码,我无法得到任何重现。然而,重要的是要意识到 ImageList 会复制位图。所以你应该在添加位图后调用它的 Dispose() 方法。如果您不这样做,那么您将面临一个严重的风险,即您将耗尽非托管内存,被位图数据消耗,并且当垃圾收集器没有足够频繁地运行以在您之后清理时致命。这不适用于片段,因为只有 10 个位图。

于 2012-04-17T00:30:06.217 回答
0

当您使用 Reflector 查看最后一行代码的作用时,您会看到 ImageList 的设置器实际上在这一行上失败了:

bool flag2 = SafeNativeMethods.ImageList_Replace(new HandleRef(this.owner, this.owner.Handle), index, new HandleRef(null, handle), new HandleRef(null, monochromeMask));

它涉及使用句柄,这些句柄在 Windows 中是有限的(如果我没记错的话,每个进程 10000 个)。因此,尽管您有很多可用内存,但您可能已达到句柄限制。

于 2012-04-16T20:46:34.653 回答