久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C# 資源釋放(轉(zhuǎn)自 愚翁專欄) - hushan_hn - JavaEye技術網(wǎng)站

 旭龍 2011-02-13
  C# 資源釋放
終于開始動手寫這篇文章了,,有個網(wǎng)友催了我好幾次,今天終于可以靜下心來完成它。
 
便于對文章的開展,,需要先明確兩個概念,。
第一個就是很多人用.Net寫程序,會談到托管這個概念,。那么.Net所指的資源托管到底是什么意思,,是相對于所有資源,還是只限于某一方面資源,?很多人對此不是很了解,,其實.Net所指的托管只是針對內(nèi)存這一個方面,并不是對于所有的資源,;因此對于Stream,,數(shù)據(jù)庫的連接,GDI+的相關對象,,還有Com對象等等,,這些資源并不是受到.Net管理而統(tǒng)稱為非托管資源。而對于內(nèi)存的釋放和回收,,系統(tǒng)提供了GC-Garbage Collector,,而至于其他資源則需要手動進行釋放。
 
那么第二個概念就是什么是垃圾,,通過我以前的文章,,會了解到.Net類型分為兩大類,一個就是值類型,,另一個就是引用類型,。前者是分配在棧上,并不需要GC回收,;后者是分配在堆上,,因此它的內(nèi)存釋放和回收需要通過GC來完成。GC的全稱為“Garbage Collector”,顧名思義就是垃圾回收器,,那么只有被稱為垃圾的對象才能被GC回收,。也就是說,一個引用類型對象所占用的內(nèi)存需要被GC回收,,需要先成為垃圾,。那么.Net如何判定一個引用類型對象是垃圾呢,.Net的判斷很簡單,,只要判定此對象或者其包含的子對象沒有任何引用是有效的,,那么系統(tǒng)就認為它是垃圾。
 
明確了這兩個基本概念,,接下來說說GC的運作方式以及其的功能,。內(nèi)存的釋放和回收需要伴隨著程序的運行,,因此系統(tǒng)為GC安排了獨立的線程。那么GC的工作大致是,,查詢內(nèi)存中對象是否成為垃圾,,然后對垃圾進行釋放和回收。那么對于GC對于內(nèi)存回收采取了一定的優(yōu)先算法進行輪循回收內(nèi)存資源,。其次,,對于內(nèi)存中的垃圾分為兩種,一種是需要調(diào)用對象的析構函數(shù),,另一種是不需要調(diào)用的,。GC對于前者的回收需要通過兩步完成,第一步是調(diào)用對象的析構函數(shù),,第二步是回收內(nèi)存,,但是要注意這兩步不是在GC一次輪循完成,即需要兩次輪循,;相對于后者,,則只是回收內(nèi)存而已。
 
很明顯得知,,對于某個具體的資源,,無法確切知道,對象析構函數(shù)什么時候被調(diào)用,,以及GC什么時候會去釋放和回收它所占用的內(nèi)存,。那么對于從C、C++之類語言轉(zhuǎn)換過來的程序員來說,,這里需要轉(zhuǎn)變觀念,。
 
那么對于程序資源來說,我們應該做些什么,,以及如何去做,,才能使程序效率最高,同時占用資源能盡快的釋放,。前面也說了,,資源分為兩種,托管的內(nèi)存資源,,這是不需要我們操心的,,系統(tǒng)已經(jīng)為我們進行管理了;那么對于非托管的資源,,這里再重申一下,,就是Stream,,數(shù)據(jù)庫的連接,,GDI+的相關對象,還有Com對象等等這些資源,需要我們手動去釋放,。
 
如何去釋放,,應該把這些操作放到哪里比較好呢。.Net提供了三種方法,,也是最常見的三種,,大致如下:
<!--[if !supportLists]-->1. <!--[endif]-->析構函數(shù);
<!--[if !supportLists]-->2. <!--[endif]-->繼承IDisposable接口,,實現(xiàn)Dispose方法,;
<!--[if !supportLists]-->3. <!--[endif]-->提供Close方法。
 
經(jīng)過前面的介紹,,可以知道析構函數(shù)只能被GC來調(diào)用的,,那么無法確定它什么時候被調(diào)用,因此用它作為資源的釋放并不是很合理,,因為資源釋放不及時,;但是為了防止資源泄漏,畢竟它會被GC調(diào)用,,因此析構函數(shù)可以作為一個補救方法,。而CloseDispose這兩種方法的區(qū)別在于,調(diào)用完了對象的Close方法后,,此對象有可能被重新進行使用,;而Dispose方法來說,此對象所占有的資源需要被標記為無用了,,也就是此對象被銷毀了,,不能再被使用。例如,,常見SqlConnection這個類,,當調(diào)用完Close方法后,可以通過Open重新打開數(shù)據(jù)庫連接,,當徹底不用這個對象了就可以調(diào)用Dispose方法來標記此對象無用,,等待GC回收。明白了這兩種方法的意思后,,大家在往自己的類中添加的接口時候,,不要歪曲了這兩者意思。
 
接下來說說這三個函數(shù)的調(diào)用時機,,我用幾個試驗結(jié)果來進行說明,,可能會使大家的印象更深。
首先是這三種方法的實現(xiàn),,大致如下:
    ///<summary>
    /// The class to show three disposal function
    ///</summary>
    public class DisposeClass:IDisposable
    {
        public void Close()
        {
            Debug.WriteLine( "Close called!" );
        }
 
        ~DisposeClass()
        {
            Debug.WriteLine( "Destructor called!" );
        }
 
        #region IDisposable Members
 
        public void Dispose()
        {
            // TODO: Add DisposeClass.Dispose implementation
            Debug.WriteLine( "Dispose called!" );
        }
 
        #endregion
    }
 
對于Close來說不屬于真正意義上的釋放,,除了注意它需要顯示被調(diào)用外,,我在此對它不多說了。而對于析構函數(shù)而言,,不是在對象離開作用域后立刻被執(zhí)行,,只有在關閉進程或者調(diào)用GC.Collect方法的時候才被調(diào)用,參看如下的代碼運行結(jié)果,。
        private void Create()
        {
            DisposeClass myClass = new DisposeClass();
        }
 
        private void CallGC()
        {
            GC.Collect();
        }
 
        // Show destructor
        Create();
        Debug.WriteLine( "After created!" );
        CallGC();
 
運行的結(jié)果為:
After created!
Destructor called!
 
顯然在出了Create函數(shù)外,,myClass對象的析構函數(shù)沒有被立刻調(diào)用,而是等顯示調(diào)用GC.Collect才被調(diào)用,。
 
對于Dispose來說,,也需要顯示的調(diào)用,但是對于繼承了IDisposable的類型對象可以使用using這個關鍵字,,這樣對象的Dispose方法在出了using范圍后會被自動調(diào)用,。例如:
    using( DisposeClass myClass = new DisposeClass() )
    {
        //other operation here
    }
 
如上運行的結(jié)果如下:
Dispose called!
 
那么對于如上DisposeClass類型的Dispose實現(xiàn)來說,事實上GC還需要調(diào)用對象的析構函數(shù),,按照前面的GC流程來說,,GC對于需要調(diào)用析構函數(shù)的對象來說,至少經(jīng)過兩個步驟,,即首先調(diào)用對象的析構函數(shù),,其次回收內(nèi)存。也就是說,,按照上面所寫的Dispose函數(shù),,雖說被執(zhí)行了,但是GC還是需要執(zhí)行析構函數(shù),,那么一個完整的Dispose函數(shù),,應該通過調(diào)用GC.SuppressFinalize(this )來告訴GC,讓它不用再調(diào)用對象的析構函數(shù)中,。那么改寫后的DisposeClass如下:
    ///<summary>
    /// The class to show three disposal function
    ///</summary>
    public class DisposeClass:IDisposable
    {
        public void Close()
        {
            Debug.WriteLine( "Close called!" );
        }
 
        ~DisposeClass()
        {
            Debug.WriteLine( "Destructor called!" );
        }
 
        #region IDisposable Members
 
        public void Dispose()
        {
            // TODO: Add DisposeClass.Dispose implementation
            Debug.WriteLine( "Dispose called!" );
            GC.SuppressFinalize( this );
        }
 
        #endregion
    }
 
通過如下的代碼進行測試,。
        private void Run()
        {
            using( DisposeClass myClass = new DisposeClass() )
            {
                //other operation here
            }
        }
 
        private void CallGC()
        {
            GC.Collect();
        }
 
        // Show destructor
        Run();
        Debug.WriteLine( "After Run!" );
        CallGC();
 
運行的結(jié)果如下:
Dispose called!
After Run!
 
顯然對象的析構函數(shù)沒有被調(diào)用。通過如上的實驗以及文字說明,,大家會得到如下的一個對比表格,。
 
析構函數(shù)
Dispose方法
Close方法
意義
銷毀對象
銷毀對象
關閉對象資源
調(diào)用方式
不能被顯示調(diào)用,會被GC調(diào)用
需要顯示調(diào)用
或者通過using語句
需要顯示調(diào)用
調(diào)用時機
不確定
確定,,在顯示調(diào)用或者離開using程序塊
確定,,在顯示調(diào)用時
 
那么在定義一個類型的時候,是否一定要給出這三個函數(shù)地實現(xiàn)呢,。
 
我的建議大致如下,。
<!--[if !supportLists]-->1.<!--[endif]-->提供析構函數(shù),避免資源未被釋放,,主要是指非內(nèi)存資源,;
<!--[if !supportLists]-->2.<!--[endif]-->對于DisposeClose方法來說,,需要看所定義的類型所使用的資源(參看前面所說),而決定是否去定義這兩個函數(shù),;
<!--[if !supportLists]-->3.<!--[endif]-->在實現(xiàn)Dispose方法的時候,一定要加上“GC.SuppressFinalize( this )”語句,,避免再讓GC調(diào)用對象的析構函數(shù),。
 
C#程序所使用的內(nèi)存是受托管的,但不意味著濫用,,好地編程習慣有利于提高代碼的質(zhì)量以及程序的運行效率,。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多