問題描述:在windows窗體中加入一ActiveX控件,例如axCanlendar,顯式釋放控件的資源,清除對它的引用後,該控件仍然無法被GC所回收。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
問題重現:在Form中加入一個axCanlendar控件及一個Button。按鈕單擊的代碼如下:
private void button1_Click(object sender, EventArgs e)
{
this.Controls.Remove(this.axCalendar1);
WeakReference wr = new WeakReference(this.axCalendar1, false);
axCalendar1.Dispose();
//Marshal.ReleaseComObject(axCalendar1.GetOcx());
axCalendar1 = null;
int i = 0;
while (wr.IsAlive)
{
i++;
GC.Collect();
MessageBox.Show(i.ToString());
}
}
--------------------------------------------------------------------------------------------------------------------------
問題分析:.net的GC是通過引用來判斷某一資源是否可以回收的,對於非托管資源,我們一般需要顯式調用其Dispose或close等函數來釋放非托管資源。但是當我們顯式調用axCanlendar的Dispose函數釋放資源,並且將其設為null後,GC仍然無法將其回收,說明它依然被某一變量引用著。那麼到底是什麼引用著它呢。我們利用windbg可以輕松地查看它的根。
0:009> !dumpheap -type AxMSACAL.AxCalendar Loading the heap objects into our cache. Address MT Size 012c94f8 00978424 336 2 AxMSACAL.AxCalendar 0:009> !gcroot 012c94f8 ESP:12e5fc:Root: 012c8bd8(WindowsApplication4.Form1)-> 012cbc78(System.Windows.Forms.LayoutEventArgs)-> 012c94f8(AxMSACAL.AxCalendar)