学霸笔记:C#开发工程师之笔记篇3C#开发工程师
今天我们的学霸笔记是写关于资源管理方面的,在编辑时对你的资源进行管理,会大大的提升机器的性能。使你开发的软件比别人的快速而且不会出现内存不够等现象,所以学好资源管理对你的编程有重要的含义。
托管堆上的内存由GC(Garbage Collector 垃圾收集器,CLR中包含GC)进行管理,其它资源由开发者负责。
.NET 提供两种管理非托管资源生命周期的机制:终结器(finalizer,由GC调用,调用发生在对象成为垃圾之后的某个时间,时间不可预料)和IDisposable接口。
GC能够判断某个实体目前是否依旧被应用程序的活动对象所引用,对于那些没有被活动对象直接或间接引用的实体,GC会将其判断为垃圾。
GC会在每次运行时压缩托管堆,压缩托管堆能够将当前仍旧使用的对象放在连续的内存中,因此空余空间也是一块连续的内存。
终结器只是一种防御手段,仅仅能够保证给定类型的对象所分配的非托管资源最终被释放。GC会把需要执行终结的对象放在专门的队列中,然后让另一个线程来执行这些对象的终结器。这样,GC可以继续执行其当前的工作,在内存中移除垃圾对象,而在下一次的GC调用中才会从内存中移除这些已被终结的对象。可以看到,需要调用终结器的对象将在内存中多停留一个GC周期的时间(实际情况会比这个更复杂一点,详情请查看下面“代”的概念),所以应该尽量少让代码的逻辑使用到终结器。
GC为了优化执行,引入了“代”(generation)的概念。可以快速地找到那些更有可能是垃圾的对象。自上一次垃圾收集以来,新创建的对象属于第0代对象。若某个对象在经历过一次垃圾收集之后仍旧存活,那么将成为第1代对象。两次及两次以上垃圾收集后仍没有被销毁的对象就变成了第2代对象。这样能将局部变量和应用程序生命周期一直使用的对象分开对待。第0代大多属于局部变量。而成员变量和全局变量则会更快地成为第1代对象,直至第2代。GC将通过减少检查第1代和第2代对象的次数来优化执行过程。在每个周期中,GC都会检查第0代对象。一般来说,大概10个周期的GC中,会有一次去同时检查第0代和第1代对象。大概100个周期的GC中,会有一次同时检查所有对象。可以看到一个需要总结的对象可能会比普通对象多停留9个GC周期。而若是再次GC的时候仍没有完成终结炒作,那么该对象将继续被提升为第2代。对于第2代的对象,往往需要100次以上的GC周期才会有机会被清除。为了避免这个性能问题,建议使用IDisposable接口。
使用了非系统资源的类型会自动在终结器中调用Dispose(),以便在使用者忘记的时候仍保证能正常释放资源,但这些资源会在内存中停留更长时间,所以最好的方案还是由使用者自己显示地使用IDisposable接口的Dispose()来释放。Dispose()并不是将对象从内存中移除,而只是让对象释放掉其中的非托管资源
Dispose()和Close()的区别(Dispose()比Close()要好一些)
Close:清理资源,对象已经不需要被终结,但一般没有调用GC.SuppressFinalize(),所以对象仍旧在终结队列中。
Dispose:清理资源,调用GC.SuppressFinalize()告知GC该对象不再需要被终结
使用IDisposable.Dispose()实现销毁非托管资源的标准销毁模式
1. 释放所有非托管资源;
2. 释放所有托管资源,包括释放事件监听程序;
3. 设定一个状态标识,表示该对象已经被销毁。若是在销毁后再次对用对象的公有方法,那么应该抛出ObjectDisposed异常;
4. 调用GC.SuppressFinalize(this),跳过终结操作;
using语句能以最简单的方式保证用户的对象可以正常销毁,即使对象在调用操作时出现异常。当有多个对象需要销毁时,可以使用多个using块或一个try/finally块。
using(){}=try{}finally{xxx.Dispose();}
下面例子能保证当obj不为null时正确清理到对象,当obj为null时,using(null)也不会报错,但不会做任何清理工作。
object obj=Factory.CreateInstance();
using(obj as IDisposable)
{
Console.Write(obj.ToString());
}
今天的这个资源管理的介绍还行吧,希望能够帮助到你。在汇鱼网将会有更多更好的文章,大家可以在汇鱼网浏览到自己想要的信息。


1914篇文章