当前位置: 代码迷 >> C# >> 关于Dispose,该怎么处理
  详细解决方案

关于Dispose,该怎么处理

热度:28   发布时间:2016-05-05 04:17:33.0
关于Dispose
当大家需要自己实现一个Dispose时,网上的经典例子都是这样写的: 
  
public void Dispose()  
 {  
     Dispose(true);  
     GC.SuppressFinalize(true);  
 }  
 protected virtual void Dispose(bool isDisposing)  
 { 
     if (_alreadyDisposed)  
         return;  
     if (isDisposing)  
     {  
         // TODO: 释放托管资源 
     }  
     // TODO: 释放非托管资源   
     _alreadyDisposed = true;  
 } 
 ~ResourceHolder() 
 { 
     Dispose(false); 
 } 
  
问题1:_alreadyDisposed为了防止Dispose反复被调用,但没防止SuppressFinalize反复被调用,不能算是很好的写法吧?
 
问题2:真有必要区分释放托管资源和非托管资源吗?因为托管资源也不需要我们来释放,实际写代码中几乎我没碰到过要写在 释放托管资源区 的代码,谁能告诉我isDisposing参数的优点到底在哪里,除了用来区分在Dispose和析构里的调用外?

------解决思路----------------------
托管资源你不用管,非托管的,你最好处理一下,不过对于托管的,也建议你别置之不理
------解决思路----------------------
当你不手动调用Dispose,而完全依赖GC回收时,托管资源的释放就会被调用两次(托管资源自己的析构函数执行了一次,然后外面那个函数的析构执行时还会调用一次Dispose),虽然不会报错,但是不调用更好
------解决思路----------------------
“_alreadyDisposed为了防止Dispose反复被调用”这并不准确。它主要是要防止“重入”。

程序中经常会有并发处理,有些处理中就需要判断一下这个状态,否则就会报错。比如说窗体上有一个监听设备消息的机制,当有消息来的时候就把消息处理了之后交给窗体绘制新的报表,或者再把报表发给另一个设备。如果窗体已经被用户点击Close按钮而正在关闭(清理环境)的过程中,设备异步监听到有消息可以读取,它就得先判断一下窗体是不是正在清理,如果清理就不能读取消息以及进行后续的计算、绘制、传输等操作了,否则就会产生一些列崩溃事件。即使不崩溃,也没有必要做这些。

所以它不一定是为了对象自己“防止被反复调用”,而是一个信号灯去通知其它并发机制“我正在关闭,因此从现在开始就立刻不要再跟我交互了”。