进来谈谈.net 对象占用内存立即释放

jxnetinfo 2006-05-15 10:15:56
1.如何立即释放一个对象占用的内存,我做过个测试 对象实现了IDispose接口
重写了Dispose方法
Dispose(true);
GC.SuppressFinalize(this);
但执行对象 Dispose方法时,该对象的状态还是继续保留,那就是对象还没从内存中消失,有什么方
法 可以立即砌底的释放对象的资源

2.有没有程序中的必要所有对象都继承IDispose接口
...全文
1793 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
shrinerain 2007-02-07
  • 打赏
  • 举报
回复
对于Image对象,如果是放在using里面,或者用完及时进行了Dispose

不会每次30M内存上升.

确认代码不存在环引用以及交叉引用.
shrinerain 2007-02-07
  • 打赏
  • 举报
回复
我是专职QA, Performance Testing是我工作内容之一.

实际上,在服务器端,很多时候IO的影响远大于内存.
shrinerain 2007-02-07
  • 打赏
  • 举报
回复
此言差亦……
你做过相册么?相册中包含的图片从文件中读来,更换图片的时候,你如何把得到的Image对象释放掉呢?.net提供GC.Collect是有用处的。并非空穴来风,我以前一个程序因为涉及到读取硬盘上不确定位置的一个图片文件,更换Picture的Image的时候,不调用GC.Collect,内存每次30M的速度镖升。加了就好了。

在必要的时候还是要自己调用释放。因为就算你的内存用了接近1G,.net可能也不会自动替你做一次释放的。这个我尝试过,虚拟内存最高用到过960M。
---------------------------------------------------------
Image对象是非托管资源对象,并不是托管对象.
另外,内存使用量小不代表系统性能高.你需要对整个系统进行CPU,内存,IO三个方面的监测,才能得出性能数据. 我想你也许没有考虑GC.Collect时系统的CPU和IO使用情况.
newskycity 2007-02-07
  • 打赏
  • 举报
回复
有理!
兔子-顾问 2007-02-07
  • 打赏
  • 举报
回复
shrinerain(圣影雨) ( ) 信誉:100 Blog 2007-2-6 19:48:31 得分: 0



永远不要强制进行垃圾回收,这样只会更加降低性能.




此言差亦……
你做过相册么?相册中包含的图片从文件中读来,更换图片的时候,你如何把得到的Image对象释放掉呢?.net提供GC.Collect是有用处的。并非空穴来风,我以前一个程序因为涉及到读取硬盘上不确定位置的一个图片文件,更换Picture的Image的时候,不调用GC.Collect,内存每次30M的速度镖升。加了就好了。

在必要的时候还是要自己调用释放。因为就算你的内存用了接近1G,.net可能也不会自动替你做一次释放的。这个我尝试过,虚拟内存最高用到过960M。
「已注销」 2007-02-07
  • 打赏
  • 举报
回复
up
halve 2007-02-07
  • 打赏
  • 举报
回复
好文章,收藏下
xiaoliangwh 2007-02-07
  • 打赏
  • 举报
回复
帮顶 !
shrinerain 2007-02-07
  • 打赏
  • 举报
回复
那么StringBuilder这样不提供Dispose的如何释放?
------------------------------------------------
StringBuilder是托管对象,这个你不用担心了,放心让CLR自己处理吧 :)
兔子-顾问 2007-02-07
  • 打赏
  • 举报
回复
或许吧。可能真如你所说的。托管资源都不要手工调用GC.Collect。可能之前做那个测试例子的时候是不够了解,没注意。我用下面代码验证了shrinerain(圣影雨)话的正确性。

OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
Image img = Image.FromFile(dlg.FileName);
if (this.BackgroundImage != null)
{
this.BackgroundImage.Dispose();
}
this.BackgroundImage = new Bitmap(img);
img.Dispose();
}

这个是可以了。不会无限增长。之前没注意,原来FromFile是不关闭文件的。学习了。


那么StringBuilder这样不提供Dispose的如何释放?
兔子-顾问 2007-02-07
  • 打赏
  • 举报
回复
晕。看来真的和你说的一样。打开图片后。.net竟然不知道自己关闭文件。这个期间,我只要图片,怎么断开图片和文件的关联?莫非要绘制一次?
shrinerain 2007-02-07
  • 打赏
  • 举报
回复
这里要说的是,托管对象是什么。非托管对象是什么。文件是系统资源,打开后需要关闭,载入导内存之后,文件操作就结束了。哪里来的非托管对象。Bitmap是System.Drawing的对象。这个是非托管的么?
----------------------------------------------------------
一切本地资源,比如文件,网络等等,都是"非托管资源",并不是说写在C#里的东西,就是"托管对象". 所谓"托管对象",是指由CLR分配在托管堆上面的类实例,而你说的本地图片,并不属于这一类.

打开一个文件,载入内存,然后并不是这个文件就"关闭"了,而是仍然"打开"的,这个文件的句柄是被当前程序独占的,其他程序并不能使用.
除非你显式的进行了"CloseHandle"的工作,在C#中就是调用Dispose()或者Close()等方法.文件才真正被"释放".

用C++来讲,就是要分清楚"指针"与"指针指向的对象"之间的关系. 举个不合适的例子,Bitmap你当作一个指针,那张图片,就是指针指向的对象. Bitmap是托管对象,但那张图片不是. C++我们常说的"野指针",就是释放了指向的对象,但是没有释放指针本身.

如果言辞不妥,请见谅... : )

shrinerain 2007-02-07
  • 打赏
  • 举报
回复
呵呵...
不好意思,我没有任何"发怒"的意思...

我之所以说"永远不要强制进行垃圾回收,这样只会更加降低性能." 是因为在我的楼上,已经有很多人解释了Dispose等是针对非托管资源. 所以我的话是以他们为前提的.

所以我的意思完整的是"对于托管对象,永远不要强制进行垃圾回收,只会更加降低性能."

而对于你说的Image,对于本地非托管资源,微软正是推荐采用GC.Collect()进行垃圾收集.

当然,世界上任何事情都不是绝对的,但是一般我们说话,都不会多于的加上一句"从概率上来讲...",是吧,:)

事实上,微软的确是完全不推荐用GC.Collect();进行托管对象的强制收集,只所以保留,毕竟因为还有非托管资源,而且有些很少的特殊场合,涉及到对象生存期,垃圾收集器工作不一定完全按我们所想.比如在多线程领域,垃圾收集器并不是工作的特别完美.






兔子-顾问 2007-02-07
  • 打赏
  • 举报
回复
GC.Collect是有参数的,你可以指定的释放哪个带里的内容,并非每次都要调用没有参数的重载。并且可以吧这个方法不要频繁调用。比如你重置界面的时候,这个时候执行一次是比较合理的。如果频繁的调用。这样可能的确会影响性能。
兔子-顾问 2007-02-07
  • 打赏
  • 举报
回复
/*
Image对象是非托管资源对象,并不是托管对象.
另外,内存使用量小不代表系统性能高.你需要对整个系统进行CPU,内存,IO三个方面的监测,才能得出性能数据. 我想你也许没有考虑GC.Collect时系统的CPU和IO使用情况.
*/

这里要说的是,托管对象是什么。非托管对象是什么。文件是系统资源,打开后需要关闭,载入导内存之后,文件操作就结束了。哪里来的非托管对象。Bitmap是System.Drawing的对象。这个是非托管的么?


//实际上,在服务器端,很多时候IO的影响远大于内存.
难道服务器的内存是无限的?io要考虑,那是数据库访问方面的,和我所说的是一回事么?



对于您的职业我不是很关心,但是钻牛角尖和使用比较绝对的言词往往会引出争论。
兔子-顾问 2007-02-07
  • 打赏
  • 举报
回复
楼上的哥们息怒。
诶。算了。是我不对。不该引用你的名字,更不该直接的说你的观点错误。
但我所说的是windows application程序,相册。并且没有任何的环、交叉之类的,简简单单一个图片框,更换图片为400+ * 600+的图而已。我所说的只是个个别的例子,只是认为你上面所说的“永远不要强制进行垃圾回收,这样只会更加降低性能.”太绝对了。
担心你的话会误导他人。

我只是举例说明gc.collect的作用是有必要自己手动调用的。我坚持我的观点,否则如果真的如你所说,永远不要用,那你该直接致电微软总部,要求取消这个没有封装好,让我们能看到,能调用的静态方法。因为它没用。
greenery 2007-02-06
  • 打赏
  • 举报
回复
up
真相重于对错 2007-02-06
  • 打赏
  • 举报
回复
用.net 就不要去考虑性能,只管用最好的机器招呼
shrinerain 2007-02-06
  • 打赏
  • 举报
回复
永远不要强制进行垃圾回收,这样只会更加降低性能.
Ivony 2006-05-15
  • 打赏
  • 举报
回复
Dispose和Finallize都是相对于非托管资源而言的,托管资源不能手动释放。可以尝试GC.Collect。

任何类包含了非托管资源,就必须实现析构函数确保非托管资源能被GC释放。同时应实现IDispose接口用于手动释放非托管资源。
加载更多回复(9)

111,092

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧