C# 为包含图标的类创建多个实例时发生OutOfMemoryException

C# 为包含图标的类创建多个实例时发生OutOfMemoryException,c#,winforms,C#,Winforms,我有一个包含图像的类: class AnyClass { Image AnyImage; string AnyString; } 当我创建该类的2000多个实例时,我遇到了一个OutOfMemoryException。 要分配给AnyClass的图像只有3个,大小为图标。 这些实例将用作ListView的数据源 有没有办法在AnyClass中通过引用指定图像? 或者,处理此类案件的方式/模式是什么 编辑: 尚未测试代码,但这与正在执行的操作类似: static void Mai

我有一个包含图像的类:

class AnyClass
{
    Image AnyImage;
    string AnyString;
}
当我创建该类的2000多个实例时,我遇到了一个
OutOfMemoryException

要分配给
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;
}
static void Main(字符串[]args)
{
List lst=新列表();
对于(int i=0;i<2000;i++)
{
添加(new AnyClass(){AnyImage=ImageList.image1,AnyString=“test”});
}
}
公共类任意类
{
公众形象;
公共字符串AnyString;
}
公共类图像列表
{
公共静态图像image1;
公共静态图像2;
公共静态图像imgae3;
}

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

这一个会引发内存异常:

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

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

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

这一个会引发内存异常:

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

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

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

class AnyClass : IDisposable
{
    public void Dispose() {
        if(AnyImage != null) { AnyImage.Dispose(); AnyImage = null; }
    }
    Image AnyImage;
    string AnyString;
}
然后,在处理完这些实例后,您应该(最好是通过
使用
)处理它们

这里的要点是,每个
图像
都使用一个GDI+句柄;当出现以下任一情况时,将释放该句柄:

  • 图像被处理(由您的代码处理,通常通过
    使用
  • 映像已完成(垃圾收集期间/之后)
如果内存充足,垃圾收集不会经常运行,因此垃圾收集不会释放丢弃的句柄。这意味着您需要提高警惕,以便在处理完每个图像后正确处理它


不过,诀窍在于知道你什么时候“完成”了图像。如果您处理了用户界面仍在使用的
图像
。。。糟糕的事情。

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

class AnyClass : IDisposable
{
    public void Dispose() {
        if(AnyImage != null) { AnyImage.Dispose(); AnyImage = null; }
    }
    Image AnyImage;
    string AnyString;
}
然后,在处理完这些实例后,您应该(最好是通过
使用
)处理它们

这里的要点是,每个
图像
都使用一个GDI+句柄;当出现以下任一情况时,将释放该句柄:

  • 图像被处理(由您的代码处理,通常通过
    使用
  • 映像已完成(垃圾收集期间/之后)
如果内存充足,垃圾收集不会经常运行,因此垃圾收集不会释放丢弃的句柄。这意味着您需要提高警惕,以便在处理完每个图像后正确处理它


不过,诀窍在于知道你什么时候“完成”了图像。如果您处理了用户界面仍在使用的
图像
。。。糟糕的事情。

你是说你只有3张不同的图片吗?不确定我是否理解正确。是的,只有3张不同的图片。其中一个将被分配到
AnyImage
是否可以显示更多代码?当图像无法加载时,可能会发生MemoryException@ibrahimBadredine通常,您会有一个资源管理器,它跟踪您的资源,这样您就不会得到同一资源的多个副本。@ibrahimBadredine您目前是如何创建映像的?在创建2000个其他项目之前,您应该能够将3个图像加载到
Image
变量中,然后将相关的
Image
引用传递到
AnyClass
实例的创建中。我怀疑你正在加载或“
new
ing”2000个重复的图像,尽管我不确定你怎么会用光小图标的内存(即使是2000个,也不算多)。你是说你只有3个不同的图像吗?不确定我是否理解正确。是的,只有3张不同的图片。其中一个将被分配到
AnyImage
是否可以显示更多代码?当图像无法加载时,可能会发生MemoryException@ibrahimBadredine通常,您会有一个资源管理器,它跟踪您的资源,这样您就不会得到同一资源的多个副本。@ibrahimBadredine您目前是如何创建映像的?在创建2000个其他项目之前,您应该能够将3个图像加载到
Image
变量中,然后将相关的
Image
引用传递到
AnyClass
实例的创建中。我怀疑您正在加载或“
new
ing”2000个重复图像,尽管我不确定小图标(即使是2000个图标,也不算多)的内存是如何耗尽的。这是因为资源管理器不缓存图像,而是每次从资源文件加载图像。事实上,它是一个属性,在资源文件的代码生成器一侧有一点代码味道,我从来没有特别喜欢过这个生成器。这是因为资源管理器不缓存映像,它每次都从资源文件加载它。事实上,它是一个属性,在资源文件的代码生成器一侧有一点代码味道,我从来没有特别注意过