在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/数据虚拟化,所以我会研究它,现在谢谢你:当虚拟化面板是你的选择时