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

本文关键字:加载 图像 1000个 情况下 内存不足 异常 | 更新日期: 2023-09-27 18:21:09

我想在桌面应用程序运行时在面板中添加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);**

但我看到一些应用程序可以加载大量图像,占用的内存可以忽略不计,例如"Batch Image Resizer"(http://www.jklnsoft.com/)

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

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

开发环境:net框架4,windowsxp,Visual Studio 2010,内存:2 GB

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

需要注意的是,100kb的JPG将比100kb占用更多的内存。100KB是磁盘上数据的压缩大小。如果你有一个800x600的32位(意味着每像素图像信息4个字节)图像,它在磁盘上可能是100kb,但你解压缩它并将其存储在内存中以显示它,这就是800*600*4=1920000字节=1.83 MB的RAM。1.83*700=用于保存所有这些图像的1281MB RAM。

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

您可能希望按需加载并缓存它们。这意味着,如果你的窗口中有20张可见的照片,你可能会加载40张照片——10张在当前位置之前,20张可见照片,10张在目前位置之后。当用户滚动时,您可以抛出任何滚动过起始位置的内容,并读入即将进入视图的内容。这样,你的记忆中只会有几本,而且你只会读更多的书。

您必须在使用位图等资源后对其进行处置。你可以用

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

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

使用CacheOption

public static ImageSource BitmapFromUri(Uri source)
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.UriSource = source;
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.EndInit();
    return bitmap;
}