我有一个表单,我在PictureBox
中动态创建了8个Panel
es,其中我显示了8个不同的图像,每个PictureBox
一个。图像是50Kb Jpeg。
问题是我想让用户同时看到300张图片,就像38张面板一样,但每当我 LOAD 图像进入PictureBox
时,我的程序就会使用5-7Mb的Ram内存< strong> MORE 。(我在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;
}
}
答案 0 :(得分:2)
您可以在很长一段时间内忽略.NET中的IDisposable接口。许多.NET程序员从不在一次性对象上调用Dispose()方法,也从不使用使用语句,并且他们的程序工作得很好。垃圾收集器使程序保持嗡嗡声,调用这些类的终结器进行清理。
但是Image和Bitmap类很特别。它们是围绕GDI +的非常瘦的托管类包装器,一个非托管api。图像可以使用 lot 的非托管内存来存储像素数据,在大图像上存储许多兆字节。将它与一个程序相结合,否则这个程序不会分配足够的托管对象来触发垃圾收集,而且你有一个胖胖的小猪问题。
完成后使用必须处理图像以避免此问题。使用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()方法,这样您就不必查看空白图片框了。
答案 1 :(得分:1)
答案 2 :(得分:1)
显示图片由OS(GDI子系统)处理,这引入了已知的内存效率低下:图像内部呈现为原始大小的位图,使用大量内存,然后缩放此位图仅用于展示。
您最好的选择是创建小型预览图像并显示它们。
另外请记住,您正在垃圾收集环境中工作:并非您在任务管理器中看到的所有内存都已真正使用,如果内存压力增加,GC将更加有害地将内存返回系统 - 事实上您的如果在可用内存较少的系统上运行,应用程序可能会使用更少的内存。