做网站怎样做才有百度快照,wordpress首页文章显示图片,wordpress循环文章,兰州网络seo上一节给大家介绍了 .Net GC的运行机制#xff0c;下面来讲下与GC相关的重要方法。 第二节#xff0e;GC关键方法解析 1.Dispose()方法 Dispose可用于释放所有资源#xff0c;包括托管的和非托管的#xff0c;需要自己实现。 大多数的非托管资源都要求手动释放#xff0c;…上一节给大家介绍了 .Net GC的运行机制下面来讲下与GC相关的重要方法。 第二节GC关键方法解析 1.Dispose()方法 Dispose可用于释放所有资源包括托管的和非托管的需要自己实现。 大多数的非托管资源都要求手动释放我们应当为释放非托管资源公开一个方法实现释放非托管资源的方法有很多种实现IDispose接口的Dispose方法是最好的这可以给使用你类库的程序员以明确的说明让他们知道怎样释放你的资源而且C#中用到的using语句快也是在离开语句块时自动调用Dispose方法。 这里需要注意的是如果基类实现了IDispose接口那么它的派生类也必须实现自己的IDispose并在其Dispose方法中调用基类中Dispose方法。只有这样的才能保证当你使用派生类实例后释放资源时连同基类中的非托管资源一起释放掉。 插曲使用using与tryfinally的区别 可以说2者没有任何区别因为using只是编辑器级的优化它与tryfinally有着相同的作用以下是一段使用using的代码它在IL阶段也是以tryfinally呈现的 C# public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { using (DataSet ds new DataSet()) { } } } MSIL .method family hidebysig instance void Page_Load(object sender,class [mscorlib]System.EventArgs e) cil managed { // 代码大小 29 (0x1d) .maxstack 2 .locals init ([0] class [System.Data]System.Data.DataSet ds, [1] bool CS$4$0000) IL_0000: nop IL_0001: newobj instance void [System.Data]System.Data.DataSet::.ctor() IL_0006: stloc.0 .try { IL_0007: nop IL_0008: nop IL_0009: leave.s IL_001b } // end .try finally { IL_000b: ldloc.0 IL_000c: ldnull IL_000d: ceq IL_000f: stloc.1 IL_0010: ldloc.1 IL_0011: brtrue.s IL_001a IL_0013: ldloc.0 IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0019: nop IL_001a: endfinally } // end handler IL_001b: nop IL_001c: ret } // end of method _Default::Page_Load 但是using的优点是在代码离开using块时using会自动调用Idispose接口的Dispose()方法。 2. GC.Collect()方法 如果我们在程序中显式的调用了垃圾收集器的collect接口那么垃圾收集器会立即运行完成内存对象的标记、压缩与清除工作使用GC.Collect(i)还可以指定回收的代然而aicken并不赞成各位同学显式调用它 ⑴. GC.Collect()做的并不只是回收内存就像第一节中介绍的在回收了内存之后GC会重新整理内存修正对象指针让空闲内存连续供CLR顺序分配内存提高新建对象的效率。内存压缩整理工作非常耗用计算资源。 ⑵.很少有人会关心到GC除了在内存吃紧以及资源空闲时运行还会在什么时候运行。 其实GC的运行时机还要受到一个叫做“策略引擎”的部件控制它会观察GC的收集频率、效率等等。它会根据GC回收效果调整GC运行的频率即当某次GC回收效果颇丰时它便会增加GC运行的频率反之亦然。 所以如果刚刚发生了一次自然的收集垃圾对象就会非常之少而此时程序又显式的进行了收集调用那么自然 GC虽然小有收获但是策略引擎就会认为这很不值得才收集了这么点垃圾也许该减少GC的次数。这样一来垃圾收集器努力保持的自然节奏就被打乱了。 同时对象类型的创建效率与频率也会被“策略引擎”捕捉到从而改变代的数量与容量。 所以额外的调用GC代价高昂甚至会降低效率。显示的调用GC.Collect()实质是在用“时间换空间”而通常在程序设计中我们推荐的设计原则是“空间换时间”比如使用各种各样的缓存。 也有例外如果你掌握了整个应用程序的情况明确的知道何时会产生大量垃圾也是可以显示调用该方法的。 综上尽量不要显示调用GC.Collect()因为服务器的CPU比内存要贵的多 3. 析构函数(Finalize()) 我们知道GC只负责释放托管资源非托管资源GC是无法释放的。类似文件操作、数据库连接等都会产用非托管资源。 Finalize方法是用于释放非托管资源的等同于C#中是析构函数C#编译器在编译构造函数时会隐式的将析构函数编译为Finalize()对应的代码并确定在finally块中执行了base.Finalize()。 析构函数中只能释放非托管资源,而不要在任何托管资源进行析构原因如下 ⑴你无法预测析构函数的运行时机它不是按顺序执行的。当析构函数被执行的时候也许你进行操作的托管资源已经被释放了。 ⑵包含Finalize()的对象需要GC的两次处理才能删除。 ⑶CLR会在单独的线程上执行所有对象的Finalize()方法无疑如果频繁的Finalize()会降低系统的性能。 下面我们来重点说说第⑵点为何包含Finalize()的对象需要两次GC才能被清除。 首先要了解与Finalize相关的两个队列终止队列(Finalization Queue)与可达队列(Freachable Queue)这两个队列存储了一组指向对象的指针。 当程序中在托管堆上分配空间时(new)如果该类含有析构函数GC将在Finalization Queue中添加一个指向该对象的指针。 在GC首次运行时会在已经被确认为垃圾的对象中遍历如果某个垃圾对象的指针被Finalization Queue包含GC将这个对象从垃圾中分离出来将它的指针储存到Freachable Queue中并在Finalization Queue删除这个对象的指针记录这时该对象就不是垃圾了——这个过程被称为是对象的复生Resurrection。当Freachable Queue一旦被添加了指针之后它就会去执行对象的Finalize()方法清除对象占用的资源。 当GC再次运行时便会再次发现这个含有Finalize()方法的垃圾对象但此时它在Finalization Queue中已经没有记录了(GC首次运行时删掉了它的Finalization Queue记录)那么这个对象就会被回收了。 至此通过GC两次运行终于回收了带有析构函数的对象。 复活实例 private void Form1_Load(object sender, EventArgs e) { Resource re new Resource(); re null;GC.Collect(); GC.WaitForPendingFinalizers(); //首次GC.Collect()没起作用哦。 label1.Text re.num.ToString(); } public class Resource { public int num; ~Resource() { 。。。 } } 看了上面的代码大家应该了解什么是复活了吧那么为什么要复生呢因为首次GC时这个对象的Finalize()方法还没有被执行如果不经过复生就被GC掉那么就连它的Finalize()一起回收了Finalize()就无法运行了所以必须先复生以执行它的Finalize()然后再回收。 还有两个方法ReRegisterForFinalize和SuppressFinalize需要讲一讲ReRegisterForFinalize是将指向对象的指针重新添加到Finalization Queue中(即召唤系统执行Finalize()方法)SuppressFinalize是将对象的指针从Finalization Queue中移除(即拒绝系统执行Finalize()方法)。 SuppressFinalize用于那些即有析构函数来释放资源又实现了Dispose()方法释放资源的情况下将GC.SuppressFinalize(this)添加至Dispose()方法中以确保程序员调用Dispose()后GC就不必再次收集了例如以下代码 public class Resource : Idisposable { private bool isDispose false; //实现Dispose()后面还有析构函数以防程序员忘记调用Dispose()方法 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!isDispose) { if (disposing) { //清理托管资源 } //清理非管资源 } isDispose true; } ~ Resource () { Dispose(false); } } 即实现Idisposable中的Dispose()方法又使用析构函数一个双保险大家不要迷惑其实在释放非托管资源时使用一个即可推荐使用前者。 4弱引用(WeakReference) 最后一个话题弱引用。在编程中对于那些大对象建议使用这种引用方式这种引用不影响GC回收我们用过了某个对象然后将其至null这样GC就可以快速回收它了但是没过多久我们又需要这个对象了没办法只好重新创建实例这样就浪费了创建实例所需的计算资源而如果不至null就会浪费内存资源。对于这种情况我们可以创建一个这个大对象的弱引用这样在内存不够时GC可以快速回收而在没有被GC回收前我们还可以再次利用该对象。 public class SomeObject { 。。。 } public static void Main() { SomeObject so new SomeObject(); WeakReference WRso new WeakReference(so); so null; Console.WriteLine(WRso.IsAlive); // True // 调用GC 手动回收。 GC.Collect(); Console.WriteLine(WRso.IsAlive); // False } 看到没在so null;后它的弱引用依然是可用的。所以对于大对象的使用aicken建议使用此种方式。另外弱引用有长短之分长弱引用在对象终结后依然追踪对象短弱引用则反之aicken不建议人为干预GC的工作成果所以推荐使用短弱引用即上面代码中的方式。 通过以上的讲解相信大家已经能够很全面的了解.Net GC方面的知识了。 转自http://www.cnblogs.com/isline/archive/2009/03/04/1402713.html转载于:https://www.cnblogs.com/zjoch/p/5237455.html