在没有内存不足的情况下在c#中加载1000个图像

时间:2012-01-24 06:10:36

标签: c# image memory-leaks out-of-memory

我想在桌面应用程序中的运行时在面板中添加 1000 图像(每个大小为(40到100)KB)。首先,用户浏览所有图像并将其加载到面板上。当它一个接一个地加载图像时,任务管理器中显示的内存使用量迅速增加,并且在一定数量的图像之后它显示“内存不足”。我的代码中的错误在哪里?

在加载700图像之前,任务管理器显示 1.05 GB 内存使用情况。 加载任务管理器后显示 2.04 GB 和2 GB RAM溢出

int picnumber = 0;
        int numberOfImages = 12;

        numberOfImages = Convert.ToInt32(textBox1.Text.ToString());

        for (int i = 0; i < numberOfImages; i++)
        {
            GroupBox gBox = new GroupBox();

            picnumber++;


            ////////////////////////////////

            // calculate the position of the groupbox where it is placed.
            if ((picnumber % 3) == 1)
            {
                x = initX;
            }
            else
            {
                if ((picnumber % 3) == 0)
                {
                    x = initX + 2 * (130 + 20);
                }
                else
                {
                    x = initX + 130 + 20;
                }

            }
            ///////////////////////////////////


            System.Drawing.Point CurrentPoint;

            CurrentPoint = panel1.AutoScrollPosition;
            y = initY + ((picnumber - 1) / 3) * (130 + 20) - (Math.Abs(panel1.AutoScrollPosition.Y));

            gBox.Text = picnumber.ToString();

            //place the groupbox in the appropriate position.
            gBox.Location = new System.Drawing.Point(x, y);
            gBox.Size = new System.Drawing.Size(130, 130);

            Bitmap btmap = new Bitmap(@"E:\43.jpg");
            // attach the image to the groupbox
            gBox.BackgroundImage = btmap;
            **gBox.BackgroundImageLayout = ImageLayout.Stretch;
            // add the groupbox that contains image to the panel.
            panel1.Controls.Add(gBox);**

但我看到一些应用程序可以加载大量图像并占用可忽略不计的内存,例如“批量图像缩放器”(http://www.jklnsoft.com/

应用程序如何处理内存?他们遵循什么机制?

在加载700个图像之前,任务管理器显示1.05 GB的内存使用量。 加载任务管理器后显示1.06 GB

开发环境: C#.net框架4, windows xp, Visual Studio 2010, RAM:2 GB

4 个答案:

答案 0 :(得分:7)

值得注意的是,100kb的JPG将占用 lot 更多的内存,而不仅仅是100kb。 100KB是磁盘上数据的压缩大小。如果你有一个32位(这意味着每像素4个字节的图像信息)图像是800x600,它可能是100kb的磁盘,但你解压缩并将其存储在内存中以便能够显示它,即800 * 600 * 4 = 1,920,000字节= 1.83 MB的RAM。 1.83 * 700 = 1,281 MB的RAM用于存放所有这些图像。

解决方案是加载图像并在内存中创建一个较小的缩略图,然后从内存中丢弃原始图像。如果你的800x600有一个80x60 @ 16位缩略图,那么只需要9.3kb的RAM来显示。其中700个只消耗6.5MB的内存 - 这是一个巨大的差异!

答案 1 :(得分:5)

您可能希望按需加载它们并缓存它们。这意味着,如果您在窗口中看到20张照片,则可能会加载40张照片 - 当前位置前10张,20张可见照片和当前位置后10张。当用户滚动时,您可以抛弃任何滚动到开始位置的内容,并阅读那些即将进入视图的内容。通过这种方式,你只会记忆中的一些内容,而且你只会阅读更多内容。

答案 2 :(得分:3)

使用后,您必须处理位图等资源。你可以这样做:

using(Bitmap btmap = new Bitmap("E:\etc...")) {
   ... code here
}

但是每次迭代都要这样做,而不是在你完成所有资源的循环之后!

答案 3 :(得分:0)

使用 CacheOption

function(req, res, next){..}