托管資源:
Net平臺中,CLR為程序員提供了一種很好的內存管理機制,使得程序員在編寫(xiě)代碼時(shí)不要顯式的去釋放自己使用的內存資源(這些在先前C和C++中是需要程序員自己去顯式的釋放的)。這種管理機制稱(chēng)為GC(garbage collection)。GC的作用是很明顯的,當系統內存資源匱乏時(shí),它就會(huì )被激發(fā),然后自動(dòng)的去釋放那些沒(méi)有被使用的托管資源(也就是程序員沒(méi)有顯式釋放的對象)。
所以托管就是.net framework 負責幫你管理內存及資源釋放,不需要自己控制,當然對象只針對托管資源(部分引用類(lèi)型), 不回收非托管資源。 像數組,用戶(hù)定義的類(lèi)、接口、委托,object,字符串等引用類(lèi)型,棧上保存著(zhù)一個(gè)地址而已,當棧釋放后, 即使對象已經(jīng)沒(méi)有用了,但堆上分配的內存還在,只能等GC收集時(shí)才能真正釋放 ;但注意int,float,DateTime之類(lèi)的值類(lèi)型,GC會(huì )自動(dòng)釋放他們占用的內存,不需要GC來(lái)回收釋放
那么非托管的資源怎么釋放回收呢?
非托管資源:
對于非托管資源,GC只能跟蹤非托管資源的生存期,而不知道如何去釋放它。這樣就會(huì )出現當資源用盡時(shí)就不能提供資源能夠提供的服務(wù),windows的運行速度就會(huì )變慢。比如當你鏈接了數據庫,用完后你沒(méi)有顯式的釋放數據庫資源,如果還是不斷的申請數據庫資源,那么到一定時(shí)候程序就會(huì )拋出一個(gè)異常。
所以,當我們在類(lèi)中封裝了對非托管資源的操作時(shí),我們就需要顯式,或者是隱式的釋放這些資源。在.Net中釋放非托管資源主要有2種方式,Dispose,Finalize,而Finalize和Dispose方法分別就是隱式和顯式操作中分別使用到的方法。
例如文件流,數據庫的連接,系統的窗口句柄,打印機資源等等,當你讀取文件之后,就需要對各種Stream進(jìn)行Dispose等操作。比如 SqlDataReader 讀取數據完畢之后,需要 reader.Dispose();等
Finalize一般情況下用于基類(lèi)不帶close方法或者不帶Dispose顯式方法的類(lèi),也就是說(shuō),在Finalize過(guò)程中我們需要隱式的去實(shí)現非托管資源的釋放,然后系統會(huì )在Finalize過(guò)程完成后,自己的去釋放托管資源。在.NET中應該盡可能的少用析構函數釋放資源,MSDN2上有這樣一段話(huà):實(shí)現 Finalize 方法或析構函數對性能可能會(huì )有負面影響,因此應避免不必要地使用它們。用 Finalize 方法回收對象使用的內存需要至少兩次垃圾回收。所以有析構函數的對象,需要兩次,第一次調用析構函數,第二次刪除對象。而且在析構函數中包含大量的釋放資源代碼,會(huì )降低垃圾回收器的工作效率,影響性能。所以對于包含非托管資源的對象,最好及時(shí)的調用Dispose()方法來(lái)回收資源,而不是依賴(lài)垃圾回收器。
Public class BaseResource:IDisposable { PrivateIntPtr handle; // 句柄,屬于非托管資源 PrivateComponet comp; // 組件,托管資源 Privateboo isDisposed = false; // 是否已釋放資源的標志 PublicBaseResource { } //實(shí)現接口方法 //由類(lèi)的使用者,在外部顯示調用,釋放類(lèi)資源 Publicvoid Dispose() { Dispose(true);// 釋放托管和非托管資源 //將對象從垃圾回收器鏈表中移除, // 從而在垃圾回收器工作時(shí),只釋放托管資源,而不執行此對象的析構函數 GC.SuppressFinalize(this); } //由垃圾回收器調用,釋放非托管資源 ~BaseResource() { Dispose(false);// 釋放非托管資源 } //參數為true表示釋放所有資源,只能由使用者調用 //參數為false表示釋放非托管資源,只能由垃圾回收器自動(dòng)調用 //如果子類(lèi)有自己的非托管資源,可以重載這個(gè)函數,添加自己的非托管資源的釋放 //但是要記住,重載此函數必須保證調用基類(lèi)的版本,以保證基類(lèi)的資源正常釋放 Protectedvirtual void Dispose(bool disposing) { If(!this.disposed)// 如果資源未釋放 這個(gè)判斷主要用了防止對象被多次釋放 { If(disposing) { Comp.Dispose();// 釋放托管資源 } closeHandle(handle);// 釋放非托管資源 handle= IntPtr.Zero; } this.disposed= true; // 標識此對象已釋放 } } 在C#中,凡是繼承了IDisposable接口的類(lèi),都可以使用using語(yǔ)句,從而在超出作用域后,讓系統自動(dòng)調用Dispose()方法。
一個(gè)資源安全的類(lèi),都實(shí)現了IDisposable接口和析構函數。提供手動(dòng)釋放資源和系統自動(dòng)釋放資源的雙保險。
聯(lián)系客服