的回收方法 净非托管资源
本文介绍了的回收方法。net非托管资源,并将其共享供您参考。具体分析如下:
有两种方法可以释放非托管资源。1.破坏者
2.实施该系统。IDisposable接口。1.析构函数构造函数可以指定创建类的实例时必须执行的某些操作。当垃圾收集器删除一个对象时,它也可以调用析构函数。乍一看,析构函数似乎是放置释放非托管资源并执行常规清理操作的代码的最佳位置。然而,事情并没有那么简单。由于垃圾收集器的运行规则,您不能将需要在某个时间运行的代码放在析构函数中。如果对象占用了有价值的重要资源,就应该尽快释放这些资源,不能等垃圾收集器释放。
复制代码如下:使用系统;使用系统。集合。通用;使用系统。Linq使用系统。文字;namespace mem release { class program { ~ program(){//orders。} static void main(string[]args){ } } }在IL DASM,你会发现没有这样的析构函数方法。编译析构函数时,C#编译器会将析构函数的代码隐式编译成Finalize()方法的相应代码,并确保执行父类的Finalize()方法,以查看这段代码中析构函数的编译情况:
复制代码如下:方法族hide by SIG虚拟实例void finalize()cil managed {//codesize 14(0xe)。maxstack 1。试试{ IL _ 0000: nop IL _ 0001: nop IL _ 0002: leave . s IL _ 000 c }//end。最后尝试{ IL _ 0004: ldarg . 0 IL _ 0005:调用实例void [mscorlib]System。object : finalize()Il _ 000 a : no pil _ 000 b : end finally }//endhandleril _ 000c : no pil _ 000d 3360 ret }//方法程序结束:3360finalize使用析构函数释放资源有几个问题:1。与C析构函数相比,C#析构函数。当C对象被删除时,其析构函数将立即执行,但由于垃圾收集器的工作方式,无法确定C#对象的析构函数何时执行。2.C#析构函数的执行会延迟对象最终从内存中删除的时间。带有析构函数的对象需要处理两次才能被删除:第一次调用析构函数时,对象不会被删除,第二次调用后对象才真正被删除。第二,IDisposable接口
IDisposable接口定义了一种模式,它为释放非托管资源提供了明确的机制,并避免了与析构函数固有的垃圾函数相关的问题。IDisposable接口声明了一个Dispose()方法,该方法不带参数,返回void。1.MSDN建议按照以下模式实现IDisposable接口
复制代码如下:公共类foo : idisposable { public void dispose(){ dispose(true);GC。SuppressFinalize(此);}受保护的虚拟void Dispose(bool disposing) { if(!m _ disposed){ if(dispose){//Release managed resources }//Release unmanaged resources m _ disposed=true;} } ~ Foo(){ Dispose(false);} private bool m _ disposed}实际上有两个函数用于在中释放资源。NET对象:处理和最终确定(1)。Finalize用于释放非托管资源,Dispose用于释放所有资源,包括托管和非托管资源(2)。void Dispose(bool disposing)函数使用disposing参数来区分当前是否由Dispose()调用。如果它是由~Foo()(也就是C#的Finalize())调用的,那么只需要释放非托管资源。(Dispose()函数由其他代码显式调用,需要释放资源,而Finalize由GC调用。Foo引用的其他托管对象可能不需要在GC调用时销毁,即使要销毁,也会被GC调用。因此,在Finalize中只需要释放非托管资源。另一方面,由于托管和非托管资源已经在Dispose()中释放,所以当GC回收对象时,没有必要再次调用Finalize,所以调用GC。Dispose()中的SuppressFinalize(this),以避免重复调用Finalize。但是,即使反复调用Finalize和Dispose,也没有问题,因为有了变量m _ disposed的存在,资源只会释放一次,多余的调用会被忽略。Finalize和Dispose确保:(1) Finalize仅释放非托管资源;(2)释放托管和非托管资源;(3)反复调用Finalize和Dispose没有问题;(4) Finalize和Dispose共享相同的资源释放策略,因此它们之间没有冲突。2、IDisposable示例
复制代码如下:namespace资源恢复{ class program { static void main(string[]args){//获取对象时使用管理实现IDisposable的类的资源/*首先判断这个对象是否实现了IDisposable接口。如果有,最好用using包装这个对象,以确保这个对象用完之后会被释放,否则很可能会出现资源泄漏的问题*/using(telphone t1=new telphone()){ t1。open();t1。说话(‘你好’);t1。bomb();//t1。dispose();//如果在这里调用Dispose()方法来释放资源,那么当t1。Open()方法执行,电话线已被切断,无法再呼叫t1。open();t1。说吧(“我回来了!”);}//这里执行完代码后,会调用Dispose方法回收Console的资源。ReadKey();}}///summary//telphone类实现IDisposable接口////summary类telphone : IDisposable {///summary///phone status/////summary private telphone状态;///summary////call////summary public void open(){ if(state==telphonestate。disposed){抛出新异常('电话线已被切断,无法打开!');} state=TelphoneState。打开;控制台。WriteLine('拿起电话');}///summary////talk////summary//param name=' s ' talk content/param public void speak(strings){ if(state!=telphonestate . open){ throw new exception('无连接');}控制台。写线;}///summary////挂断电话////summary public void bomb(){ state=telphonetstate . close;控制台。WriteLine('挂断电话');} IDisposable成员}///summary////电话状态枚举////summary enum telphone状态{打开、关闭、处置}}程序运行结果如下图所示:
第三,析构函数和IDisposable混合调用的例子
复制代码代码如下:公共类资源持有者: IDisposable { private bool isDispose=false;//显示调用的处理方法public void Dispose(){ Dispose(true);GC .SuppressFinalize(此);} //实际的清除方法受保护的虚拟void Dispose(bool Dispose){ if(!isDisposed) { if (disposing) { //这里执行清除托管对象的操作。} //这里执行清除非托管对象的操作} isDisposed=true} //析构函数~资源持有者(){ Dispose(false);}}
希望本文所述对大家的ASP。网程序设计有所帮助。
版权声明:的回收方法 净非托管资源是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。