积极答复者
加载Picture内存不释放

问题
-
自从C#一产生,我就认为它很优美,到现在除了它漂亮外,我也不知它能作什么? 做个图像,加载到Picture占用内存一直占下去,不释放,不象Delphi,C++等来个Free,Delete 可以见到内存马上减小
来看一下呢,可以帮我改一下代码吗?
我的图片文件有30M的样子
Bitmap bit = null;
//两个按钮交替点击N次,内存会占到几百M,吓人呢?
private void toolStripButton1_Click(object sender, EventArgs e)
{
pictureBox1.Image = null;
bit=new Bitmap(@"c:\2\a.bmp");
pictureBox1.Image = bit;
}
private void toolStripButton2_Click(object sender, EventArgs e)
{
pictureBox1.Image = null;
bit=new Bitmap("c:\\1\\b.jpg");
pictureBox1.Image = bit;
}
- 已编辑 Sheng Jiang 蒋晟Moderator 2011年10月10日 22:08 标题含糊
答案
-
.NET 的内存释放是有GC完成的。
不需要你自己管理,这么说来,好比你住c或者delphi的旅馆,你必须自己洗衣服,而你住ms的。net旅馆,你只需要把衣服扔到外面,自然后GC大妈帮你洗好,在你需要的时候给你送来。
family as water- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
用C#,你需要把自己看成一个领袖
至于内存管理这种低级的事情,不是一个当领袖的人应该去管的.
比如,古德里安,我完全相信他开一辆坦克,要比绝大多数德国坦克兵开得帅
但身为五星上将,更应该考虑的是如何部署调动几百上千辆坦克
这远比把一辆坦克开得好要产生出大得多的价值
我相信,你在更高级别上产生的价值也要远比操纵更好几M的内存要多得多
- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
楼主您的代码本身就会造成内存泄漏。因为 Bitmap 是一个系统资源,是 Windows 的 HBITMAP 包装来的,您必须调用 Dispose() 释放这个资源,否则 Windows 一直为它保留内存。
注意 bitmap = null 这句话只是将 bitmap 这个变量的引用清掉了,而不是把它占的内存释放掉了。
不是说 CLR 有了 GC 您就什么事情都不用做了,您要 use GC wisely. 特别是有操作系统资源时。比如 IO,GDI,注册表,网络等。在使用一个类型时,先看看它是否实现了 IDisposable 接口,有的,则必须用 using 语句用完他后立即回收掉。
另外我想反驳一下这个标题,要知道现在开发者使用的 70% 以上的软件,都使用了 .NET Framework。包括 Windows 自己,还有 Visual Studio,SQL Server 等。不是说 C# 中看不中用,是看您如何用。
Mark Zhou- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
dear
天~并非使用null就是释放,你必须对物件呼叫Close()或Dispose()方法,要改善代码必须要对C#语言以及.NET CLR有相当程度了解,若单纯只是要了解.NET CLR你可参考以下
CLR via C#(第3版)/微軟技術叢書 (for .net 4.0)
http://tl.zxhsd.com/kgsm/ts/big5/2010/09/21/1826692.shtml框架設計<第2版>--CLR Via C#/微軟技術叢書 (for .net 2.0)
http://tl.zxhsd.com/kgsm/ts/big5/2008/12/16/1013003.shtml若要使用设计模式来优化代码,可参考程杰老师所写的大话设计模式
http://tl.zxhsd.com/kgsm/ts/big5/2008/12/16/1219546.shtml
秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
那我觉得真的是你的图片太大了。
可以试一下 在加载之前,先把 pictureBox1.Image 给释放掉,然后再赋值给它。
private void toolStripButton1_Click(object sender, EventArgs e) { pictureBox1.Image.Dispose(); currentIndex = currentIndex > PictureList.Count - 2 ? 0 : ++currentIndex; pictureBox1.Image = Image.FromFile(PictureList[currentIndex]); // Console.WriteLine(PictureList[currentIndex].ToString()); } private void toolStripButton2_Click(object sender, EventArgs e) { pictureBox1.Image.Dispose(); currentIndex = currentIndex > PictureList.Count - 2 ? 0 : ++currentIndex; pictureBox1.Image = Image.FromFile(PictureList[currentIndex]); // Console.WriteLine(PictureList[currentIndex].ToString()); }
在我的电脑(Visual Studio 2010,.Net Framework 4.0,Windows 7)上测试是没有问题的。用这种办法可以见到成效的。希望对您有用。
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Lie YouModerator 2011年10月20日 2:10
-
首先你得确定pictureBox1.Image 不为空,然后才能释放掉。
建议你可以加个if 条件判断:
if (pictureBox1.Image != null) { //先释放掉,然后加载 } else { //加载图片 }
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Lie YouModerator 2011年10月20日 2:10
-
.Net 中的GC是不定时触发的和隐式执行。只要内存足够使用,他就不会被触发。
但是我们可以显示的指定GC执行,前面有提到的GC.Collect()。
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Lie YouModerator 2011年10月20日 2:10
全部回复
-
.NET 的内存释放是有GC完成的。
不需要你自己管理,这么说来,好比你住c或者delphi的旅馆,你必须自己洗衣服,而你住ms的。net旅馆,你只需要把衣服扔到外面,自然后GC大妈帮你洗好,在你需要的时候给你送来。
family as water- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
用C#,你需要把自己看成一个领袖
至于内存管理这种低级的事情,不是一个当领袖的人应该去管的.
比如,古德里安,我完全相信他开一辆坦克,要比绝大多数德国坦克兵开得帅
但身为五星上将,更应该考虑的是如何部署调动几百上千辆坦克
这远比把一辆坦克开得好要产生出大得多的价值
我相信,你在更高级别上产生的价值也要远比操纵更好几M的内存要多得多
- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
楼主您的代码本身就会造成内存泄漏。因为 Bitmap 是一个系统资源,是 Windows 的 HBITMAP 包装来的,您必须调用 Dispose() 释放这个资源,否则 Windows 一直为它保留内存。
注意 bitmap = null 这句话只是将 bitmap 这个变量的引用清掉了,而不是把它占的内存释放掉了。
不是说 CLR 有了 GC 您就什么事情都不用做了,您要 use GC wisely. 特别是有操作系统资源时。比如 IO,GDI,注册表,网络等。在使用一个类型时,先看看它是否实现了 IDisposable 接口,有的,则必须用 using 语句用完他后立即回收掉。
另外我想反驳一下这个标题,要知道现在开发者使用的 70% 以上的软件,都使用了 .NET Framework。包括 Windows 自己,还有 Visual Studio,SQL Server 等。不是说 C# 中看不中用,是看您如何用。
Mark Zhou- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
dear
天~并非使用null就是释放,你必须对物件呼叫Close()或Dispose()方法,要改善代码必须要对C#语言以及.NET CLR有相当程度了解,若单纯只是要了解.NET CLR你可参考以下
CLR via C#(第3版)/微軟技術叢書 (for .net 4.0)
http://tl.zxhsd.com/kgsm/ts/big5/2010/09/21/1826692.shtml框架設計<第2版>--CLR Via C#/微軟技術叢書 (for .net 2.0)
http://tl.zxhsd.com/kgsm/ts/big5/2008/12/16/1013003.shtml若要使用设计模式来优化代码,可参考程杰老师所写的大话设计模式
http://tl.zxhsd.com/kgsm/ts/big5/2008/12/16/1219546.shtml
秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/- 已标记为答案 Lie YouModerator 2011年10月20日 2:09
-
像Stone,AceBear,Mark Zhou, 余小章所说的一样,.Net 中有自己的垃圾回收机制--GC。
http://msdn.microsoft.com/zh-cn/library/0xy59wtx.aspx
一般情况下,GC是隐式执行,但他又允许我们显示调用去释放不需要的对象内存:
GC.Collect();
或许您的代码这样修改会好点:private void button4_Click(object sender, EventArgs e) { pictureBox1.Image = null; Bitmap bit = new Bitmap(@"D:\rocky's files\pic\Myslelf.jpg"); pictureBox1.Image = bit; GC.Collect(); } private void button2_Click(object sender, EventArgs e) { pictureBox1.Image = null; Bitmap bit = new Bitmap(@"D:\rocky's files\pic\Myslelf.jpg"); pictureBox2.Image = bit; GC.Collect(); }
_希望帮得到您。
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
我用这段代码测试,每次运行占用的内存都在3M左右。我有2900多张图片,大概在22M左右。
List<string> PictureList = new List<string>(); int currentIndex = -1; private void button2_Click(object sender, EventArgs e) { currentIndex = currentIndex > PictureList.Count - 2 ? 0 : ++currentIndex; pictureBox1.Image = Image.FromFile(PictureList[currentIndex]); } private void Form1_Load(object sender, EventArgs e) { PictureList.AddRange(System.IO.Directory.GetFiles(@"D:\rocky's files\pic", "*.jpg")); if (PictureList.Count > 0) { currentIndex = 0; string picName = "(" + currentIndex + ")"; pictureBox1.Image = Image.FromFile(PictureList[currentIndex]); } }
您可以试一下。
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
你的方法不行呢,浏览文件夹下的图片,内存占用增加到出现内存不足的错误呢?
private void toolStripButton1_Click(object sender, EventArgs e)
{
currentIndex = currentIndex > picturelist.Count - 2 ? 0 : ++currentIndex;
pictureBox1.Image=Image.FromFile(picturelist[currentIndex]);
}
private void toolStripButton2_Click(object sender, EventArgs e)
{
currentIndex = currentIndex > picturelist.Count - 2 ? 0 : ++currentIndex;
pictureBox1.Image = Image.FromFile(picturelist[currentIndex]);
}
private void Form1_Load(object sender, EventArgs e)
{
picturelist.AddRange(Directory.GetFiles("c:\\1", "*.jpg"));
if (picturelist.Count > 0)
{
currentIndex = 0;
string picName = "(" + currentIndex + ")";
pictureBox1.Image = Image.FromFile(picturelist[currentIndex]);
}
} -
那我觉得真的是你的图片太大了。
可以试一下 在加载之前,先把 pictureBox1.Image 给释放掉,然后再赋值给它。
private void toolStripButton1_Click(object sender, EventArgs e) { pictureBox1.Image.Dispose(); currentIndex = currentIndex > PictureList.Count - 2 ? 0 : ++currentIndex; pictureBox1.Image = Image.FromFile(PictureList[currentIndex]); // Console.WriteLine(PictureList[currentIndex].ToString()); } private void toolStripButton2_Click(object sender, EventArgs e) { pictureBox1.Image.Dispose(); currentIndex = currentIndex > PictureList.Count - 2 ? 0 : ++currentIndex; pictureBox1.Image = Image.FromFile(PictureList[currentIndex]); // Console.WriteLine(PictureList[currentIndex].ToString()); }
在我的电脑(Visual Studio 2010,.Net Framework 4.0,Windows 7)上测试是没有问题的。用这种办法可以见到成效的。希望对您有用。
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Lie YouModerator 2011年10月20日 2:10
-
如果我不是从磁盘加载图片,是从数据库中读取图片,用Dispose会找不到实例呢》?
private void VreadImage()
{
SqlConnection cn = LinkDB.LinkDBSqlconnection(cnstr);
if (cn.State == ConnectionState.Closed) cn.Open();
string cmdstr = "select cardImage from CardImage where autoid=" +
recordNo;
SqlCommand cmd = new SqlCommand(cmdstr, cn);
Byte[] b = (Byte[])cmd.ExecuteScalar();
if (b.Length > 0)
{
MemoryStream ms = new MemoryStream(b, true);
ms.Write(b, 0, b.Length);
//pictureBox1.Image.Dispose();//有了这句会出错的???
this.pictureBox1.Image = Image.FromStream(ms);
ms.Dispose();
}
cn.Dispose();
} -
首先你得确定pictureBox1.Image 不为空,然后才能释放掉。
建议你可以加个if 条件判断:
if (pictureBox1.Image != null) { //先释放掉,然后加载 } else { //加载图片 }
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Lie YouModerator 2011年10月20日 2:10
-
如果我不是从磁盘加载图片,是从数据库中读取图片,用Dispose会找不到实例呢》?
private void VreadImage()
{
SqlConnection cn = LinkDB.LinkDBSqlconnection(cnstr);
if (cn.State == ConnectionState.Closed) cn.Open();
string cmdstr = "select cardImage from CardImage where autoid=" +
recordNo;
SqlCommand cmd = new SqlCommand(cmdstr, cn);
Byte[] b = (Byte[])cmd.ExecuteScalar();
if (b.Length > 0)
{
MemoryStream ms = new MemoryStream(b, true);
ms.Write(b, 0, b.Length);
//pictureBox1.Image.Dispose();//有了这句会出错的???
this.pictureBox1.Image = Image.FromStream(ms);
ms.Dispose();
}
cn.Dispose();
}dear
你得在释放前检查是否为空,这跟数据库一点关系都没有.
http://www.dotblogs.com.tw/yc421206/archive/2009/11/01/11370.aspx
秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/ -
.Net 中的GC是不定时触发的和隐式执行。只要内存足够使用,他就不会被触发。
但是我们可以显示的指定GC执行,前面有提到的GC.Collect()。
Best Regards,
Rocky Yue[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Lie YouModerator 2011年10月20日 2:10