当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > .NET框架下的自动内存管理

ASP.NET
C# Quoted-Printable编码、解码
asp.net Google的translate工具翻译 API
.NET读取所有目录下文件正则匹配文本电子邮件
asp.net 半角全角转化工具
AjaxControlToolKit 显示浏览者本地语言的方法
asp.net HTML文件上传标签
ASP.NET 绑定DataSet中的多个表
ASP.NET 重定向的几种方法小结
Asp.Net 重定向必须要知道的一些资料
ASP.NET 导出到Excel时保留换行的代码
Asp.Net Cache缓存使用代码
document.getElementsByName和document.getElementById 在IE与FF中不同实现
GridView单元格合并
asp.net 大文件上传控件
asp.net 日期函数 某月的第一天和最后一天的日期
asp.net 时间类 一周的周一和周末的日期
C# javaScript函数的相互调用
asp.net membership 密码重设
"虚拟路径"..."映射到另一个应用程序,这是不允许的!
如何传值在2个页面之间 要求不刷新父页面,并且不能用Querystring传值

ASP.NET 中的 .NET框架下的自动内存管理


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-03   浏览: 219 ::
收藏到网摘: n/a

C#使用的自动内存管理,使用开发者从繁重的手工分配、释放内存的操作解放出来。内存的自动管理是由垃圾回收器来执行。一个对象使用内存的生命周期是这样的:
  当对象被创建时,它便分配了一定的内存,当构造器中的代码开始运行时,这个对象就“活”了。
当这个对象或者是它的任何一部分在可以预计的将来已经没有任何作用时,这个对象将不会再使用,它就应当被销毁。
  一旦这个对象符合了对销毁的条件,在一定的时间后,这个对象的销毁器就将被执行,一般情况下,除非被显示地重写,这个销毁器只能运行一次。
  一旦销毁器被运行,那么这个对象以及它任何一部分都不可能在以后的运行中使用,这甚至包括正在运行的销毁器。这时这个对象将被认为是不可见的,它所占的资源将会被回收。
  最后由垃圾回收器释放这个对象所占的资源。
  垃圾回收器控制着这些对象的使用信息并利用这些信息控制内存,比如内存哪里创建了一个新对象,什么时候重新创建对象以及什么时候将这个对象释放。
  像其它的语言一样,C#假定确实存在这样一个垃圾回收器,而且这个垃圾回收器可以管理很大范围的内存。比如,C#并不要求销毁器一事实上要执行,也不要求对象一旦无用则马上回收。
  当然垃圾回收器的行为也是可以被控制的,这个控制的方法来自于System.GC类。这个类可以请求回收、销毁器运行等操作。
  下面是一个例子。
class A
{
~A() {
Console.WriteLine("Destruct instance of A");
}
}
class B
{
object ref;
public B(object o) {
ref = o;
}
~B() {
Console.WriteLine("Destruct instance of B");
}
}
class TMest
{
static void Main() {
B b = new B(new A());

b = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
  上面的程序创建了类A与类B的一个实例,当变量b被赋于null值时,A与B均符合了垃圾回收器的回收要求。此时就没有任何代码能够访问它们了。
  执行的结果,下面两种情况都有可能:
Destruct instance of A
Destruct instance of B

Destruct instance of B
Destruct instance of A
  因为上面的程序的并没有限制这两个对象被回收的顺序。
  在某些敏感的条件下,有关区分“销毁”与“回收”操作条件的定义是非常重要的:
class A
{
~A() {
Console.WriteLine("Destruct instance of A");
}
public void F() {
Console.WriteLine("A.F");
TMest.RefA = this;
}
}
class B
{
public A Ref;
~B() {
Console.WriteLine("Destruct instance of B");
Ref.F();
}
}
class TMest
{
public static A RefA;
public static B RefB;
static void Main() {
RefB = new B();
RefA = new A();
RefB.Ref = RefA;
RefB = null;
RefA = null;
// A and B now eligible for destruction
GC.Collect();
GC.WaitForPendingFinalizers();
// B now eligible for collection, but A is not
if (RefA != null)
Console.WriteLine("RefA is not null");
}
}
  在上面的程序中,如果垃圾回收器选择先执行类B的销毁器,那么执行的结果为:
Destruct instance of A
Destruct instance of B
A.F
RefA is not null
  注意,虽然实例A并没有被使用,但是从输出的结果大家可以看到A的销毁器确实执行了,而且连A的方法F也被执行了。同时我们也注意至,一个对象销毁器的运行又可能使一个实例变得可用。在这种情况下,实例B销毁器的执行使得先前并没有调用的实例A也可以被访问了,而这一种就是引用RefA的功劳,当调用WaitForPendingFinalizers方法以后,实例B就可以被垃圾回收器回收,而此时的实例A则还不可以。
  为了区分这些行为,大家编写程序时,最好只管理当前类的销毁器,而不要采用引用其它类的实例或者静态字段。