C# Dispose模式
目的
為了及時釋放寶貴的非托管資源和托管資源,并且保證資源在被 gc 回收的時候可以正確釋放資源,同時兼顧執(zhí)行效率。
必須遵循的事實
1 . ?托管資源釋放:
由另一線程的 gc 進行釋放,當托管的對象沒有被引用時,就會在“適當?shù)臅r候”進行回收。
如果定義了析構(gòu)函數(shù),回收的時候會調(diào)用析構(gòu)函數(shù)(實際執(zhí)行可能有差別),之后釋放對象占用的內(nèi)存。
當類有析構(gòu)函數(shù)時, gc 會分分兩步來釋放,如果沒有析構(gòu)函數(shù)或者指定不需要調(diào)用析構(gòu)函數(shù)時,只需要一步就能釋放。
2.? 非托管資源必須顯式釋放
方案
1.? 把資源釋放都放在析構(gòu)函數(shù)里
可以保證資源都釋放,但是由于 gc 調(diào)用時機的不確定性,導致寶貴的非托管資源無法及時釋放。
2.? 寫個釋放函數(shù),手動是調(diào)用
如果忘了釋放的話, 托管資源會被 gc 釋放,但非托管資源就無法釋放
3. ?Dispose 模式。參考下面的代碼
手動調(diào)用Dispose() 可以釋放所有資源,并且在 gc 標記不需要再調(diào)用析構(gòu)函數(shù),從而提高了效率。如果忘記調(diào)用Dispose(), 則當 gc 調(diào)用析構(gòu)函數(shù)的時候也會把非托管資源釋放掉。
參考代碼
public interface IDisposable {void Dispose(); } public class DisposablClass : IDisposable {//是否回收完畢bool _disposed;public void Dispose(){Dispose(true);GC.SuppressFinalize(this); //標記gc不在調(diào)用析構(gòu)函數(shù)}~DisposableClass(){Dispose(false);}private void Dispose(bool disposing){if(_disposed) return; //如果已經(jīng)被回收,就中斷執(zhí)行if(disposing){//TODO:釋放本對象中管理的托管資源}//TODO:釋放非托管資源_disposed = true;} }可能存在的疑問
既然 gc 是另外一線程執(zhí)行的,為什么Dispose(bool)函數(shù)里不加鎖?
因為如果可以主動調(diào)用的時候,肯定此對象不是死對象,也不會被回收,因此不會同時調(diào)用到哪里不太對,但又說不上來。
為什么析構(gòu)函數(shù)調(diào)用的dispose(false)不釋放托管資源?
因為析構(gòu)函數(shù)由 gc 來調(diào)用,gc 會依次釋放所有的死對象(不可到達),釋放的順序是隨機的,如果在一個對象的析構(gòu)里調(diào)用了一個本次 gc已經(jīng)釋放的對象,就會發(fā)生釋放兩次的錯誤。
總結(jié)
以上是生活随笔為你收集整理的C# Dispose模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dotnet-httpie 0.2.0
- 下一篇: C# 中使用HttpClient读取大型