C# 托管非托管資源釋放


1、C#幾乎所有對象都為托管對象,不同點是有的對象封裝了非托管資源。

2、C#大部分對象在進行垃圾回收時都可以回收,包括非托管資源,因為非托管資源都已經通過C#類進行了封裝,會將非托管資源的釋放放在析構函數中,同時會實現IDipose接口。

3、IDipose作用是可以通過using手動提前釋放,節約寶貴的資源。

4、在C#中,凡是繼承了IDisposable接口的類,都可以使用using語句,從而在超出作用域后,讓系統自動調用Dispose()方法。 一個資源安全的類,都實現了IDisposable接口和析構函數。提供手動釋放資源和系統自動釋放資源的雙保險。

5、類似FileStream,會同時實現IDipose,及定義~FileStream(),~FileStream()作用是使用者沒有調用IDipose,在GC回收時再回收非托管資源,否則非托管資源只有在程序停止之后才會釋放。

析構函數只能由垃圾回收器調用。Despose()方法只能由類的使用者調用。

 

總結區分托管資源和非托管資源

(1)托管資源一般是指被CLR控制的內存資源,這些資源的管理可以由CLR來控制,例如程序中分配的對象,作用域內的變量等。 

(2)非托管資源是CLR不能控制或者管理的部分,這些資源有很多,比如文件流,數據庫的連接,系統的窗口句柄,打印機資源 等,這些資源一般情況下不存在於Heap(內存中用於存儲對象實例的地方)中。

托管資源:從文字上看就是托付給別人管理,就像.NET的CLR,java的jvm

例子:

public class SourceManager : IDisposable
{
    private bool disposed = false;
    //非托管資源
    private IntPtr handle;
    //托管資源
    FileStream fs = null;
    public SourceManager()
    {
    }

    //由垃圾回收器調用,釋放非托管資源
    ~SourceManager()
    {
        //GC調用,終結 
        Dispose(false);// 釋放非托管資源
    }

    //實現接口方法
    //由類的使用者,在外部顯示調用,釋放類資源
    public void Dispose()
    {
        Dispose(true);// 釋放托管和非托管資源

        //將對象從垃圾回收器鏈表中移除,
        // 從而在垃圾回收器工作時,只釋放托管資源,而不執行此對象的析構函數
        GC.SuppressFinalize(this);
    }

    //參數為true表示釋放所有資源,只能由使用者調用
    //參數為false表示釋放非托管資源,只能由垃圾回收器自動調用
    //如果子類有自己的非托管資源,可以重載這個函數,添加自己的非托管資源的釋放
    //但是要記住,重載此函數必須保證調用基類的版本,以保證基類的資源正常釋放
    protected virtual void Dispose(bool disposing)
    {
        // 如果資源未釋放 這個判斷主要用了防止對象被多次釋放
        if (!this.disposed)
        {
            if (disposing && fs != null)
            {
                // 釋放托管資源
                fs.Dispose();
            }

            //釋放非托管資源
            //...
            handle = IntPtr.Zero;

            disposed = true; // 標識此對象已釋放
        }

    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM