【问题标题】:load 1000 images in c# without out-of-memory exception在 C# 中加载 1000 张图像而不会出现内存不足异常
【发布时间】:2012-01-24 06:10:35
【问题描述】:

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

开发环境: C#.net 框架 4, 视窗XP, 视觉工作室 2010, 内存:2 GB

【问题讨论】:

  • 我认为Bitmap 没有得到处理,这篇文章应该可以帮助你stackoverflow.com/questions/2808753/…
  • 在加载这些图像之前,您在应用中使用了 1gb..?
  • 我认为结合使用 user1118321 的答案,结合 Chris Heald 的答案会很好地为您服务。

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


【解决方案1】:

请务必注意,100kb 的 JPG 会比 100kb 占用更多的内存很多。 100KB 是磁盘上数据的压缩大小。如果您有一个 800x600 的 32 位(这意味着图像信息的每个像素 4 个字节)图像,它在磁盘上可能是 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 的 RAM - 一个巨大的差异!

【讨论】:

    【解决方案2】:

    您可能希望按需加载它们并缓存它们。这意味着如果您的窗口中有 20 张可见的照片,您可能会加载 40 张照片 - 当前位置之前的 10 张、可见的 20 张照片和当前位置之后的 10 张。当用户滚动时,您可以丢弃任何滚动超过起始位置的内容,并阅读那些很快就会出现的内容。这样一来,您的记忆中就只有一些,而您只会阅读更多的内容。

    【讨论】:

    • 换句话说,你手机里的画廊是做什么的。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      使用 CacheOption

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

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 1970-01-01
        • 1970-01-01
        • 2015-02-19
        • 2014-03-03
        • 2018-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多