一般.net的垃圾回收机制会在过程结束后进行垃圾回收,但是垃圾回收是比较消耗系统资源的,所以不可能经常被调用。
创新互联公司-专业网站定制、快速模板网站建设、高性价比龙子湖网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式龙子湖网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖龙子湖地区。费用合理售后完善,10多年实体公司更值得信赖。
如果你需要强制进行垃圾回收,可在过程最后添加如下代码:
GC.Collect()
强制进行垃圾回收
.net 有自己的资源回收机制GC。
如果变量不再使用了,所有引用该变量的其它变量也都没用了(dispose或者赋值为空了),那么这些没用的变量会定时的被GC自动回收,不需要自己去管理。
如果非要自己释放资源的话,可以使用 GC.Collect() 进行释放,但是并不能保证一次GC.Collect()就可以释放掉所有没有用的资源,可能要经过好几轮GC.Collect()才能释放干净。
所以还是建议不要手动回收了,让系统根据要求自动回收吧。
1.如果你释放的是托管托管代码的内存,那么托管代码的内存管理是自动的,.NET可以保证我们的托管程序在结束时全部释放。
2.如果是非托管资源时.NET就不能自动管理了,下面是释放非托管资源内存方法
当我们利用如数据库、文件等非托管资源时,就要用到.NET Framework中的标准: IDisposable接口。按照标准,所有有需要手动释放非托管资源的类都得实现此接口。这个接口只有一个方法,Dispose(),不过有相对的 Guidelines指示如何实现此接口,在这里我向大家说一说。实现IDisposable这个接口的类需要有这样的结构:
[Visual Basic]
Public Class Base
Implements IDisposable
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Me.Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
' 托管类
End If
' 非托管资源释放
End Sub
Protected Overrides Sub Finalize()
Me.Dispose(False)
MyBase.Finalize()
End Sub
End Class
Public Class Derive
Inherits Base
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
' 托管类
End If
' 非托管资源释放
MyBase.Dispose(disposing)
End Sub
End Class
我们要实现Dispose方法,实现这个Dispose方法的几个准则:
它不能扔出任何错误,重复的调用也不能扔出错误。也就是说,如果我已经调用了一个对象的Dispose,当我第二次调用Dispose的时候程序不应该出错,简单地说程序在第二次调用Dispose时不会做任何事。这些可以通过一个flag或多重if判断实现。
一个对象的Dispose要做到释放这个对象的所有资源。拿一个继承类为例,继承类中用到了非托管资源所以它实现了IDisposable接口,如果继承类的基类也用到了非托管资源那么基类也得被释放,基类的资源如何在继承类中释放呢?当然是通过一个virtual/Overridable方法了,这样我们能保证每个Dispose都被调用到。这就是为什么我们的设计有一个virtual/Overridable的Dispose方法。注意我们首先要释放继承类的资源然后再释放基类的资源。
因为非托管资源一定要被保障正确释放所以我们要定义一个Finalizer来避免程序员忘了调用Dispose的情况。上面的设计就采用了这种形式。如果我们手动调用Dispose方法就没有必要再保留Finalizer了,所以在Dispose中我们用了GC.SupressFinalize 将对象从Finalizer表去掉,这样再回收时速度会更快。
那么那个disposing和"托管类"是怎么回事呢?是这样:在"托管类"中写所有你想在调用Dispose时让其处于可释放状态的托管代码。还记得我们说过我们不知道托管代码是什么时候释放的吗?在这里我们只是去掉成员对象的引用让它处于可被回收状态,并不是直接释放内存。在"托管类"中这里我们也要写上所有实现了IDisposable的成员对象,因为他们也有Dispose,所以也需要在对象的Dispose中调用他们的 Dispose,这样才能保证第二个准则。disposing是为了区分Dispose的调用方法,如果我们手动调用那么为了第二个准则"托管类"部分当然得执行,但如果是Finalizer调用的Dispose,这时候对象已经没有任何引用,也就是说对象的成员自然也就不存在了(无引用),也就没有必要执行"托管类"部分了,因为他们已经处于可被回收状态了。好了,这就是IDisposable接口的全部了。现在让我们来回想一下,以前我们可能认为有了 Dispose内存就会马上被释放,这是错误的。只有非托管内存才会被马上释放,托管内存的释放由GC管理,我们不用管。
分类: 电脑/网络 程序设计 其他编程语言
问题描述:
别跟我说VB2000自动释放内存,曾经深信这句话的我,如今已是伤痕累累,好几个大项目都差点毁在vb的内存问题上,C#我倒不知道..VB的回收内存速度太慢了,这只是保守的说,其实本人认为它根本不会回收内存.就算全部用上gc.collet也回收不了,而且越用越慢
在使用我的项目的时候,随着窗口的开开关关\控件的调用,内存一直飙,从14MB左右一路疯狂飙高,40分钟系统就崩溃了...上了补丁的XP可以不死机,但就定着不动了..如果虚拟内存文件大,可以维持到撑满,但录一条记录平均要等一个小时!!!!!!!,后来我学乖了开始nothing全局变量(工作量惊人...),结果内存开始有下走的现象(原来是一路向上..只占不放)但内存还是呈曲线上飙,40分钟到200多MB,于是我开始释放局部变量,在每个方法中都要释放!!!!!!!!!!!!!!!!!!!!!,而且还要区分哪些是引用!痛苦啊!!!
...结果三个月之后,满面憔悴的我终于发现内存接近正常了,虽然还不是释放的很干净,但能保证在一段时间内不会崩溃了..至少客户做的时候没再提过意见...我并没有优化什么代码,只是痛苦的释放了一些全局和局部变量,结果内存就不消耗的那么厉害了,你说奇怪不奇怪..但内存始终不是释放的那么干净,我算过了一分钟内曲线飙高2MB左右,有时更多照这样一来,真是早死不如晚死,想想将来还不如用java重新做呢...各位可怜可怜我吧,有什么好主意整理vb2000的内存的好东东,就告诉我吧!!!!!!!!!!我真的受不了了!!!!!有没有什么方法可以重新分配内存呢,就算会造成页中断我也在所不惜!!!!
另外Me.Refresh()是什么意义,能释放内存么?
解析:
很简单,你没有正确理解VB的内存自动回收机制,仔细看一下MSDN,好好研究一下相关的内容。其实JAVA的内存自动回收机制与VB是类似的,如果你用VB.NET做不好,换用JAVA照样做不好。
其实,你已经发现了为什么内存不能回收,只是你没意识到罢了。
为什么要用全局变量呢?给你举个极端的例子吧:建立一个全局的Hashtable,然后将程序中创建的每一个对象实例加入到这个hashtable中,那么你将看到内存一直猛增,直到崩溃。
正确的作法是:
1、尽量不用、少用全局变量和静态变量
2、如果没有必要,就不要把对象实例加到全局或静态的Hashtable、ArrayList之类的 *** 中去,除非你是想自己建立一个对象缓冲池
3、如果你自己要建立对象缓冲池,就一定要注意对象的清理,尽早将不用的对象从池中删除
4、找本好一点的数据结构,仔细学学其中关于自动内存回收的那几种机制,以后在程序中不要违反它们的要求前提条件。