3、Finalization Queue和Freachable Queue程序員
這兩個隊列和.net對象所提供的Finalize方法有關。這兩個隊列並不用於存儲真正的對象,而是存儲一組指向對象的指針。當程序中使用了new操做符在Managed Heap上分配空間時,GC會對其進行分析,若是該對象含有Finalize方法則在Finalization Queue中添加一個指向該對象的指針。在GC被啓動之後,通過Mark階段分辨出哪些是垃圾。再在垃圾中搜索,若是發現垃圾中有被Finalization Queue中的指針所指向的對象,則將這個對象從垃圾中分離出來,並將指向它的指針移動到Freachable Queue中。這個過程被稱爲是對象的復生(Resurrection),原本死去的對象就這樣被救活了。爲何要救活它呢?由於這個對象的Finalize方法尚未被執行,因此不能讓它死去。Freachable Queue平時不作什麼事,可是一旦裏面被添加了指針以後,它就會去觸發所指對象的Finalize方法執行,以後將這個指針從隊列中剔除,這是對象就能夠安靜的死去了。.net framework的System.GC類提供了控制Finalize的兩個方法,ReRegisterForFinalize和SuppressFinalize。前者是請求系統完成對象的Finalize方法,後者是請求系統不要完成對象的Finalize方法。ReRegisterForFinalize方法其實就是將指向對象的指針從新添加到Finalization Queue中。這就出現了一個頗有趣的現象,由於在Finalization Queue中的對象能夠復生,若是在對象的Finalize方法中調用ReRegisterForFinalize方法,這樣就造成了一個在堆上永遠不會死去的對象,像鳳凰涅槃同樣每次死的時候均可以復生。數據庫
託管資源:ide
Net中的全部類型都是(直接或間接)從System.Object類型派生的。性能
CTS中的類型被分紅兩大類——引用類型(reference type,又叫託管類型[managed type]),分配在內存堆上,值類型(value type)。值類型分配在堆棧上。如圖spa
值類型在棧裏,先進後出,值類型變量的生命有前後順序,這個確保了值類型變量在推出做用域之前會釋放資源。比引用類型更簡單和高效。堆棧是從高地址往低地址分配內存。.net
引用類型分配在託管堆(Managed Heap)上,聲明一個變量在棧上保存,當使用new建立對象時,會把對象的地址存儲在這個變量裏。託管堆相反,從低地址往高地址分配內存,如圖指針
.net中超過80%的資源都是託管資源。code
非託管資源:對象
ApplicationContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Font,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader,Pen,Regex,Socket,StreamWriter,Timer,Tooltip ,文件句柄,GDI資源,數據庫鏈接等等資源。可能在使用的時候不少都沒有注意到!接口
.NET的GC機制有這樣兩個問題:
首先,GC並非能釋放全部的資源。它不能自動釋放非託管資源。
第二,GC並非實時性的,這將會形成系統性能上的瓶頸和不肯定性。
GC並非實時性的,這會形成系統性能上的瓶頸和不肯定性。因此有了IDisposable接口,IDisposable接口定義了Dispose方法,這個方法用來供程序員顯式調用以釋放非託管資源。使用using 語句能夠簡化資源管理。
示例
/// <summary>
/// 執行SQL語句,返回影響的記錄數
/// </summary>
/// <param name="SQLString">SQL語句</param>
/// <returns>影響的記錄數</returns>
public
static
int
ExecuteSql(
string
SQLString)
{
using
(SqlConnection connection =
new
SqlConnection(connectionString))
{
using
(SqlCommand cmd =
new
SqlCommand(SQLString, connection))
{
try
{
connection.Open();
int
rows = cmd.ExecuteNonQuery();
return
rows;
}
catch
(System.Data.SqlClient.SqlException e)
{
connection.Close();
throw
e;
}
finally
{
cmd.Dispose();
connection.Close();
}
}
}
}