您的位置:首頁 > 軟件資訊 > 編程技巧 > 網(wǎng)站開發(fā)
來源:北大青鳥飛迅校區(qū)|發(fā)布時間:2013-04-17 10:06:08
如何清理C#.Net中的非托管代碼?最近幫助其它項目組Review代碼,發(fā)現(xiàn)有些地方實現(xiàn)了IDispose接口,同時也發(fā)現(xiàn)了一些關(guān)于IDispose的問題:
1、A類型實現(xiàn)了IDispose接口,B類型里面含有A類型的字段,B類型沒有實現(xiàn)IDispose接口。
2、一個類里面實現(xiàn)了Finalize終結(jié)器,同時也實現(xiàn)了IDispose接口,但在Dispose方法里面沒有調(diào)用GC.SuppressFinalize(this)方法。
下面我對以上兩個問題分別分析一下,并提出解決方案。
問題1
如果A類型里面有非托管資源需要在實現(xiàn)的IDispose接口里面釋放,由于B類型沒有實現(xiàn)IDispose接口,B類型的使用者要想釋放A類型的非托管資源并不方便.這樣的話,就有可能忘記了釋放A類型的非托管資源。
解決方案:
實現(xiàn)B類型的IDispose接口,在Dispose方法里面調(diào)用A類型的Dispose方法.這樣,B類型的使用者在調(diào)用B類型Dispose的同時,就把A類型的Dispose也調(diào)用了。
問題2
在Dispose方法里面沒有調(diào)用GC.SuppressFinalize(this)方法,會有什么問題呢,這樣會導(dǎo)致垃圾回收器不能對 這個類型的對象及時回收. 當GC開始工作的時候,它首先將沒有終結(jié)器的垃圾對象從內(nèi)存中移除,有終結(jié)器的所有對象則添加到一個垃圾隊列當中。GC會調(diào)用一個新線程來執(zhí)行這些對象的 終結(jié)器。當終結(jié)器執(zhí)行完畢后,這個對象會從隊列中被移除。這個對象在隊列中移除之后,當GC再次開始工作的時候,這個對象才能夠被回收,所以有終結(jié)器的對 象會比沒有的在內(nèi)存中保留更長的時間。在后面我會對這里再詳細的描述一下。
解決方案:
在Dispose方法中調(diào)用GC.SuppressFinalize(this)方法.這樣的話,就不會把有終結(jié)器的對象則添加到垃圾隊列當中.
切入正題
.net中,非托管代碼清理有兩種方式:Finalize方式和Dispose方式。
Finalize方式:通過對自定義類型實現(xiàn)一個Finalize方法來釋放非通過資源。
從.net2.0開始,C#編譯器不能對Finalize進行顯示的調(diào)用和重寫,必須使用析構(gòu)函數(shù)來實現(xiàn)它。
class A
{
~A()
{
釋放資源;
}
}
上面的代碼就是通過Finalize方式來釋放資源的跟C++用析構(gòu)函數(shù)釋放資源的代碼很象。
但是它實現(xiàn)方式和C++不同,因為它是由垃圾回收器來管理內(nèi)存的。
大家看到了,用Finalize方式釋放非托管資源很簡單,但是如果你了解了他的實現(xiàn)方式,你可能就不會選擇用它來釋放非托管資源。
那Finalize方式在.net內(nèi)部是如何實現(xiàn)的呢?
當GC(垃圾回收器)開始工作的時候,它首先將沒有終結(jié)器的垃圾對象從內(nèi)存中移除,有終結(jié)器的所有對象則添加到一個終止化隊列當中。GC會調(diào)用一個 新線程來執(zhí)行這些對象的終結(jié)器。當終結(jié)器執(zhí)行完畢后,這些對象會從隊列中被移除。這時候由于這些對象在第一次檢測到的時候沒有被釋放,它們將會進入第1代 對象,直到GC檢測到第0代對象和第1代對象再次充滿時,這時候GC才會把剛才那些對象釋放掉,所以有終結(jié)器的對象會比沒有的在內(nèi)存中保留更長的時間。
招生熱線: 4008-0731-86 / 0731-82186801
學校地址: 長沙市天心區(qū)團結(jié)路6號
Copyright © 2006 | 湖南大計信息科技有限公司 版權(quán)所有
湘ICP備14017520號-3