在C#中显示大量内存非常低的图像?

在C#中显示大量内存非常低的图像?,c#,image,memory,picturebox,C#,Image,Memory,Picturebox,我有一个表单,在该表单中,我在面板中动态创建了8个PictureBoxes,其中我显示了8个不同的图像,每个PictureBox。图像为50Kb Jpeg。 问题是,我想让用户也能看到300张图片,就像38个面板一样,但每次我将图片加载到PictureBoxes中,我的程序都会使用5-7Mb的Ram内存更多(我从Windows的任务管理器中看到) 我怎样才能减少这个增量?我的照片没有那么大,我只想显示预览,我不在乎质量。 下面是我如何创建PictureBoxes的: private void b

我有一个表单,在该表单中,我在
面板中动态创建了8个
PictureBox
es,其中我显示了8个不同的图像,每个
PictureBox
。图像为50Kb Jpeg。 问题是,我想让用户也能看到300张图片,就像38个面板一样,但每次我图片加载到
PictureBox
es中,我的程序都会使用5-7Mb的Ram内存更多(我从Windows的任务管理器中看到) 我怎样才能减少这个增量?我的照片没有那么大,我只想显示预览,我不在乎质量。 下面是我如何创建
PictureBox
es的:

private void buttonAdd_Click(object sender, EventArgs e)
{     
  Panel pan = new Panel();
  PictureBox pic1 = new PictureBox();
  pic1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
  pic1.Location = new System.Drawing.Point(208, 5);
  pic1.Name = "panel" + ctr.Count().ToString() + "pictureBox1";
  pic1.Size = new System.Drawing.Size(100, 100);
  pic1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
  ///
  /// Same thing other 7 times with differents name and location
  ///      
  pan.Location = new System.Drawing.Point(12, 55);
  pan.Name = "panel" + ctr.Count().ToString();
  pan.Size = new System.Drawing.Size(1088, 129);
  pan.TabIndex = 0;
  pan.AllowDrop = true;
  pan.BackColor = System.Drawing.SystemColors.ControlLight;
  pan.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;           
  pan.Controls.Add(pic1);
  ///
  /// Same thing other 7 times 
  ///        
  this.Controls.Add(pan);
  }
下面是我如何填写的:

void buttonClickEvent(object sender, EventArgs e)
    {
        string[] files= Directory.GetFiles("mylocalpath");
        foreach(string x in files)
        {
            string imgIndex= x.Remove(0,x.LastIndexOf("_")+1).Remove(1);
            PictureBox pic=pictureBox1; 
            //I get it everytime from imgIndex and sender's parent,
            //too much code to show now
            pic.ImageLocation = x;
        }

    }

也许UI虚拟化可以帮助您

你想一次显示所有这些图片框吗

我理解你的问题,你只想一次展示其中的8个

请看下面的文章


尤其是

也许UI虚拟化可以帮助您

你想一次显示所有这些图片框吗

我理解你的问题,你只想一次展示其中的8个

请看下面的文章


尤其是显示图片的

由操作系统(GDI子系统)处理,这导致了已知的内存效率低下:图像在内部以其原始大小渲染为位图,使用大量内存,然后仅为显示而缩小该位图

你最好的办法是创建小的预览图像并显示它们


还要记住,您是在垃圾收集环境中工作的:并不是所有在Task Manager中看到的内存都被真正使用了,如果内存压力增大,GC将更积极地向系统返回内存-事实上,如果在可用内存较少的系统上运行,应用程序可能会使用较少的内存。

显示图片由操作系统(GDI子系统)处理,这导致了一个已知的内存效率低下:图像在内部以其原始大小渲染为位图,使用大量内存,然后该位图仅为显示而缩小

你最好的办法是创建小的预览图像并显示它们


还要记住,您是在垃圾收集环境中工作的:并不是所有在Task Manager中看到的内存都被真正使用了,如果内存压力增大,GC将更积极地向系统返回内存-事实上,如果在可用内存较少的系统上运行,应用程序可能会使用较少的内存。

您可以在很长一段时间内忽略.NET中的IDisposable接口。许多.NET程序员从未对一次性对象调用Dispose()方法,也从未使用using语句,他们的程序工作得很好。垃圾收集器让程序继续运行,调用此类类的终结器进行清理

但是图像和位图类是特殊的。它们是围绕非托管api GDI+的非常精简的托管类包装器。图像可以使用大量非托管内存来存储像素数据,在大型图像上存储很多兆字节。如果再加上程序没有分配足够的托管对象来触发垃圾收集,那么你就有了一个胖猪问题

您必须在使用完图像后处理图像,以避免此问题。这在使用PictureBox.ImageLocation属性时有点困难,PictureBox类使用辅助线程加载图像。它无法自行处理以前的映像,也无法知道该映像是否可能在其他地方使用。你必须帮助:

    foreach(string x in files)
    {
        string imgIndex = x.Remove(0,x.LastIndexOf("_")+1).Remove(1);
        PictureBox pic = pictureBox1; 
        //...
        if (pic.Image != null) pic.Image.Dispose();
        pic.Image = null;
        pic.ImageLocation = x;
    }

或者改用Image.FromFile()方法,这样您就不必查看空图片框。

您可以在很长一段时间内忽略.NET中的IDisposable接口。许多.NET程序员从未对一次性对象调用Dispose()方法,也从未使用using语句,他们的程序工作得很好。垃圾收集器让程序继续运行,调用此类类的终结器进行清理

但是图像和位图类是特殊的。它们是围绕非托管api GDI+的非常精简的托管类包装器。图像可以使用大量非托管内存来存储像素数据,在大型图像上存储很多兆字节。如果再加上程序没有分配足够的托管对象来触发垃圾收集,那么你就有了一个胖猪问题

您必须在使用完图像后处理图像,以避免此问题。这在使用PictureBox.ImageLocation属性时有点困难,PictureBox类使用辅助线程加载图像。它无法自行处理以前的映像,也无法知道该映像是否可能在其他地方使用。你必须帮助:

    foreach(string x in files)
    {
        string imgIndex = x.Remove(0,x.LastIndexOf("_")+1).Remove(1);
        PictureBox pic = pictureBox1; 
        //...
        if (pic.Image != null) pic.Image.Dispose();
        pic.Image = null;
        pic.ImageLocation = x;
    }

或者改用Image.FromFile()方法,这样您就不必查看空图片框。

首先,不要信任taskmanager!尝试覆盖
OnPaint
OnRefresh
,这样您就可以加载图像、绘制图像并忘记它。仅适用于静态未隐藏图像。首先,不要信任taskmanager!尝试覆盖
OnPaint
OnRefresh
,这样您就可以加载图像、绘制图像并忘记它。仅适用于静态未隐藏的图像。抱歉,如果我没有解释清楚,我想同时显示大量图像,按8分组,但总是同时显示大量图像。大约80个面板,这意味着640个图像。但是,我不知道什么是UI/数据虚拟化,所以我会研究它,现在谢谢:当虚拟化面板是您的选择时,如果我没有解释清楚,我想同时显示大量图像,按8分组,但总是同时显示大量图像。大约80个面板,这意味着640个图像。但是,我不知道什么是UI/数据虚拟化,所以我会研究它,现在谢谢你:当虚拟化面板是你的选择时