1

我有一个包含图像的类:

class AnyClass
{
    Image AnyImage;
    string AnyString;
}

我有一个OutOfMemoryException当我创建这个类的 2000 多个实例时,我
要分配的图像AnyClass只有 3 个和图标大小。
这些实例将用作 ListView 的数据源。

有没有办法通过引用分配图像AnyClass
或者处理这种情况的方式/模式是什么?

已编辑:
尚未测试代码,但这与正在执行的操作类似:

static void Main(string[] args)
{
    List<AnyClass> lst = new List<AnyClass>();
    for (int i = 0; i < 2000; i++)
    {
        lst.Add(new AnyClass() { AnyImage = ImageList.image1, AnyString = "test" });
    }
}

public class AnyClass
{
    public Image AnyImage;
    public string AnyString;
}

public class ImageList
{
    public static Image image1;
    public static Image image2;
    public static Image imgae3;
}
4

2 回答 2

1

我在我的资源项目中添加了一个示例图像,并且我编写了两个代码:

这个抛出一个内存异常:

List<AnyClass> lst = new List<AnyClass>();
for (int i = 0; i < 20000; i++)
{
    lst.Add(new AnyClass() { AnyImage = ConsoleApplication1.Properties.Resources.Image1, AnyString = "test" });
}

这个没有:

var image1 = ConsoleApplication1.Properties.Resources.Image1;
List<AnyClass> lst = new List<AnyClass>();
for (int i = 0; i < 20000; i++)
{
    lst.Add(new AnyClass() { AnyImage = image1, AnyString = "test" });
}

在任务管理器中,您可以看到第一个代码正在使用内存,除非没有更多。
第二个代码立即运行。

此外,您可以尝试以下代码:

var instance1 = ConsoleApplication1.Properties.Resources.Image1;
var instance2 = ConsoleApplication1.Properties.Resources.Image1;

Console.Write(instance1 == instance2); -- output false

因此,如果您在项目的资源中使用图像,则必须先对其进行缓存,否则每次调用资源时都会创建图像的新实例。

于 2013-04-17T09:40:48.693 回答
0

听起来这与 GDI+ 句柄有关,而不是内存。特别是,我希望您在完成后不会处理图像。由于AnyClass封装了图像,因此感觉AnyClass应该是IDisposable

class AnyClass : IDisposable
{
    public void Dispose() {
        if(AnyImage != null) { AnyImage.Dispose(); AnyImage = null; }
    }
    Image AnyImage;
    string AnyString;
}

然后你应该在处理完using这些实例后(最好是通过)处理它们。

这里的重点是每个都Image使用 GDI+ 句柄;该句柄在以下任一情况下被释放:

  • 图像被处理(由您的代码,通常通过using
  • 图像最终确定(在垃圾收集期间/之后)

如果您有足够的内存,垃圾收集将不会经常运行,因此垃圾收集不会释放丢弃的句柄。这意味着您需要警惕在处理完每张图像后正确处理它。

不过,诀窍是知道您何时“完成”了图像。如果您处理ImageUI 仍在使用的...坏事。

于 2013-04-17T09:55:34.090 回答