眾所周知,在.net的世界里,程序員只負(fù)責(zé)使用new創(chuàng)建對象,而對象的銷毀則完全交給垃圾回收器負(fù)責(zé),只有當(dāng)發(fā)生垃圾回收的時候,.net中的類型才會被銷毀。這通常不會引起什么不妥。但是,當(dāng)使用了非托管的com對象的時候,則會帶來特別的問題。
com使用引用計數(shù)來確定對象的生存期,com客戶每次引用對象的時候,就調(diào)用
IUnKnown->AddRef(),而每次釋放對象的時候,就調(diào)用
IUnKnown->Release(),一旦引用計數(shù)達(dá)到零,就釋放實例。
問題就這樣產(chǎn)生了,讓我們看下面的代碼:
這是在CSDN的asp.net版廣為流傳的一段使用Excel com組件導(dǎo)出excel文件到客戶端的c#代碼,在添加這段代碼之前,運行了添加com引用的向?qū)А?BR>Excel.application  oExcel;  
Excel.Workbook  oBook;  
Object  oMissing  =  System.Reflection.Missing.Value;  
oExcel  =  new  Excel.Application();  
oBook  =  oExcel.Workbooks.Add(oMissing);  
for  (int  i=1;i  <=4;i++)  
{  
 oExcel.Cells[i,1]=i.ToString();  
 oExcel.Cells[i,2]=  "'bbb2  ";  
 oExcel.Cells[i,3]=  "'ccc3  ";  
 oExcel.Cells[i,4]=  "'aaa4  ";  
}  
oBook.Saved  =  true;  
oExcel.UserControl  =  false;  
string filename = DateTime.Now.Ticks.ToString();
string  mm=Server.MapPath(  ".")+ "http://" + filename + ".xls";//服務(wù)器保存地址  
oExcel.ActiveWorkbook.SaveCopyAs  (mm);  
oExcel.Quit();
//GC.Collect();
Response.Redirect(filename+".xls"); 
這段代碼能夠?qū)崿F(xiàn)導(dǎo)出文件的功能,但是如果察看Windows任務(wù)管理器,就會發(fā)現(xiàn)如下圖的精彩場面

于是,有人就在代碼中加了一句“GC.Collect();”,很好,EXCEL.EXE沒有那么多了,如下圖。
但是,如何能徹底釋放呢?
幸運的是,在.net中,允許程序員顯式地自己調(diào)用com的Release方法,這個方法經(jīng)過.net的包裝,叫做System.Runtime.InteropServices.Marshal.ReleaseComObject,在上面的代碼中,
調(diào)用“GC.Collect();”之前,先調(diào)用
“System.Runtime.InteropServices.Marshal.ReleaseComObject((object)oExcel);”,
把引用計數(shù)減一,這樣,引用計數(shù)就變成了零,垃圾回收發(fā)生時,oExcel所對應(yīng)的com對象,就被掃地出門。
新聞熱點
疑難解答