日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
C#.Net中的非托管代碼清理

這兩天幫助其它項(xiàng)目組Review代碼,發(fā)現(xiàn)有些地方實(shí)現(xiàn)了IDispose接口,同時(shí)也發(fā)現(xiàn)了一些關(guān)于IDispose的問題:

目前創(chuàng)新互聯(lián)已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、禹城網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

1.A類型實(shí)現(xiàn)了IDispose接口,B類型里面含有A類型的字段,B類型沒有實(shí)現(xiàn)IDispose接口

2.一個(gè)類里面實(shí)現(xiàn)了Finalize終結(jié)器,同時(shí)也實(shí)現(xiàn)了IDispose接口,但在Dispose方法里面沒有調(diào)用GC.SuppressFinalize(this)方法.

下面我對(duì)以上兩個(gè)問題分別分析一下,并提出解決方案。

問題1

如果A類型里面有非托管資源需要在實(shí)現(xiàn)的IDispose接口里面釋放,由于B類型沒有實(shí)現(xiàn)IDispose接口,B類型的使用者要想釋放A類型的非托管資源并不方便.這樣的話,就有可能忘記了釋放A類型的非托管資源.

解決方案:

實(shí)現(xiàn)B類型的IDispose接口,在Dispose方法里面調(diào)用A類型的Dispose方法.這樣,B類型的使用者在調(diào)用B類型Dispose的同時(shí),就把A類型的Dispose也調(diào)用了.

問題2

在Dispose方法里面沒有調(diào)用GC.SuppressFinalize(this)方法,會(huì)有什么問題呢,這樣會(huì)導(dǎo)致垃圾回收器不能對(duì) 這個(gè)類型的對(duì)象及時(shí)回收. 當(dāng)GC開始工作的時(shí)候,它首先將沒有終結(jié)器的垃圾對(duì)象從內(nèi)存中移除,有終結(jié)器的所有對(duì)象則添加到一個(gè)垃圾隊(duì)列當(dāng)中。GC會(huì)調(diào)用一個(gè)新線程來執(zhí)行這些對(duì)象的 終結(jié)器。當(dāng)終結(jié)器執(zhí)行完畢后,這個(gè)對(duì)象會(huì)從隊(duì)列中被移除。這個(gè)對(duì)象在隊(duì)列中移除之后,當(dāng)GC再次開始工作的時(shí)候,這個(gè)對(duì)象才能夠被回收,所以有終結(jié)器的對(duì) 象會(huì)比沒有的在內(nèi)存中保留更長(zhǎng)的時(shí)間。在后面我會(huì)對(duì)這里再詳細(xì)的描述一下.

解決方案:

在Dispose方法中調(diào)用GC.SuppressFinalize(this)方法.這樣的話,就不會(huì)把有終結(jié)器的對(duì)象則添加到垃圾隊(duì)列當(dāng)中.

切入正題

.net中,非托管代碼清理有兩種方式:Finalize方式和Dispose方式.

Finalize方式:通過對(duì)自定義類型實(shí)現(xiàn)一個(gè)Finalize方法來釋放非通過資源.

從.net2.0開始,C#編譯器不能對(duì)Finalize進(jìn)行顯示的調(diào)用和重寫,必須使用析構(gòu)函數(shù)來實(shí)現(xiàn)它.

class A
{
~A()
{
釋放資源;
}
}

上面的代碼就是通過Finalize方式來釋放資源的跟C++用析構(gòu)函數(shù)釋放資源的代碼很象.

但是它實(shí)現(xiàn)方式和C++不同,因?yàn)樗怯衫厥掌鱽砉芾韮?nèi)存的.

大家看到了,用Finalize方式釋放非托管資源很簡(jiǎn)單,但是如果你了解了他的實(shí)現(xiàn)方式,你可能就不會(huì)選擇用它來釋放非托管資源.

那Finalize方式在.net內(nèi)部是如何實(shí)現(xiàn)的呢?

當(dāng)GC(垃圾回收器)開始工作的時(shí)候,它首先將沒有終結(jié)器的垃圾對(duì)象從內(nèi)存中移除,有終結(jié)器的所有對(duì)象則添加到一個(gè)終止化隊(duì)列當(dāng)中。GC會(huì)調(diào)用一個(gè) 新線程來執(zhí)行這些對(duì)象的終結(jié)器。當(dāng)終結(jié)器執(zhí)行完畢后,這些對(duì)象會(huì)從隊(duì)列中被移除。這時(shí)候由于這些對(duì)象在第一次檢測(cè)到的時(shí)候沒有被釋放,它們將會(huì)進(jìn)入第1代 對(duì)象,直到GC檢測(cè)到第0代對(duì)象和第1代對(duì)象再次充滿時(shí),這時(shí)候GC才會(huì)把剛才那些對(duì)象釋放掉,所以有終結(jié)器的對(duì)象會(huì)比沒有的在內(nèi)存中保留更長(zhǎng)的時(shí)間。

提示:垃圾回收器把托管堆中的對(duì)象分為3代,分別是0,1,2.一般分配為:0代約256K,1代約是2MB,第2代約是MB,代齡越高,容量就越 大,顯然效率也就越低.首先被添加到托管堆中的對(duì)象被定為第0代,當(dāng)?shù)?代充滿時(shí),就會(huì)執(zhí)行垃圾回收,未被回收的對(duì)象代領(lǐng)將提升1代.

由于以上原因應(yīng)該避免僅使用Finalize方式釋放非托管資源.

Dispose模式:在自定義類中實(shí)現(xiàn)IDispose接口,在接口中的Dispose方法中對(duì)非托管資源進(jìn)行釋放.閑話少說,上代碼

public class MyResourceRelease: IDisposable
{
/// 保證資源只用釋放一次
private bool _alreadyDisposed = false;
/// 用來判斷釋放資源的類別(托管和非托管)
protected virtual void Dispose(bool isDisposing)
{
if(_alreadyDisposed)
{
return;
}
if(isDisposing)
{
//釋放托管資源
}
//釋放非托管資源
_alreadyDisposed = true;
}
public void Dispose()
{
Dispose(true);
}
}

上面的代碼就是用Dispose方式釋放資源的方法.因?yàn)樯厦孀远x的Dispose(bool isDisposing)方法是virtual的,所以還可以在派生類里面對(duì)它進(jìn)行override

public class MyDerivedResource: MyResourceRelease
{
private bool _disposed = false;
protected override void Dispose(bool isDisposing)
{
if(_disposed)
{
return;
}
try
{
if(isDisposing)
{
//釋放托管資源
}
//釋放非托管資源
_disposed = true;
}
finally
{
base.Dispose(isDisposing);
}
}
}

這樣可以確保釋放繼承鏈上所有對(duì)象的引用資源,在整個(gè)繼承層次中傳播Dispose模式.

#p#

那用Dispose方式非托管資源就是最好的方法了嗎?

其實(shí)不然,因?yàn)轭愋蛯?shí)現(xiàn)了IDispose接口,這個(gè)類的使用者必須顯示調(diào)用Dispose方法,或者在創(chuàng)建該類型對(duì)象的時(shí)候使用using關(guān)鍵 字,對(duì)于一些粗心的使用者可能會(huì)忘記調(diào)用Dispose方法,或者沒有使用using關(guān)鍵字,這樣就導(dǎo)致了非托管資源沒有釋放的后果.

最佳方案

同時(shí)實(shí)現(xiàn)終結(jié)器和Dispose方式.這樣對(duì)于細(xì)心的使用者直接顯示調(diào)用Dispose方法會(huì)提高垃圾回收的性能,對(duì)于粗心的使用者雖然忘記了調(diào)用Dispose方法,但也不至于使得非托管資源得不到釋放.

注意這里用到了GC. SuppressFinalize(this)方法.

代碼如下:

public class MyResourceRelease: IDisposable
{
~MyResourceRelease()
{
Dispose(false);
}
/// 保證資源只用釋放一次
private bool _alreadyDisposed = false;
/// 用來判斷釋放資源的類別(托管和非托管)
protected virtual void Dispose(bool isDisposing)
{
if(_alreadyDisposed)
{
return;
}
if(isDisposing)
{
//釋放托管資源
}
//釋放非托管資源
_alreadyDisposed = true;
}
public void Dispose()
{
Dispose(true);
//阻止GC把該對(duì)象放入終結(jié)器隊(duì)列
GC.SuppressFinalize(this);
}
}


分享文章:C#.Net中的非托管代碼清理
轉(zhuǎn)載注明:http://www.5511xx.com/article/cdhscjs.html