我應該處理的每個字體在System.Drawing.FontFamily.Families
屬性,它返回我FontFamily
類,它實現IDisposable
陣列?我應該處置FontFamily.Families結果嗎?
我應該處理這也實現在極少數情況下IDisposable
當它們被一個屬性訪問器返回的情況下,其他任何類實例或數組?
我應該處理的每個字體在System.Drawing.FontFamily.Families
屬性,它返回我FontFamily
類,它實現IDisposable
陣列?我應該處置FontFamily.Families結果嗎?
我應該處理這也實現在極少數情況下IDisposable
當它們被一個屬性訪問器返回的情況下,其他任何類實例或數組?
我使用Reflector查看了代碼,並且我可以告訴您,當您訪問該屬性時,將爲每個字體使用SafeNativeMethods.Gdip.GdipCloneFontFamily()
分配大量字體句柄。
你應該如果它不是太難。如果你不這樣做,終結器將釋放爲每種字體分配的操作系統句柄,但是如果有很多字體,你不需要很長時間來處理它們。在終結者被調用之前可能需要一段任意長的時間。
如果你多次訪問Families[]
屬性,你可以用很多未發佈OS手柄可能導致問題的結束。
這裏是爲FontFamily
類型的Dispose()方法:
private void Dispose(bool disposing)
{
if (this.nativeFamily != IntPtr.Zero)
{
try
{
SafeNativeMethods.Gdip.GdipDeleteFontFamily(new HandleRef(this, this.nativeFamily));
}
catch (Exception exception)
{
if (ClientUtils.IsCriticalException(exception))
{
throw;
}
}
finally
{
this.nativeFamily = IntPtr.Zero;
}
}
}
請注意,您將在調用GdipDeleteFontFamily()
這將是釋放字體的操作系統底層的手柄被錯過了。
(旁註:微軟對這種事情的文檔是非常差的,因爲他們的樣本代碼通常會忽略處置字體的問題)
這裏是Families
實現:
public FontFamily[] Families
{
get
{
int numFound = 0x0;
int status = SafeNativeMethods.Gdip.GdipGetFontCollectionFamilyCount(new HandleRef(this, this.nativeFontCollection), out numFound);
if (status != 0x0)
{
throw SafeNativeMethods.Gdip.StatusException(status);
}
IntPtr[] gpfamilies = new IntPtr[numFound];
int num3 = 0x0;
status = SafeNativeMethods.Gdip.GdipGetFontCollectionFamilyList(new HandleRef(this, this.nativeFontCollection), numFound, gpfamilies, out num3);
if (status != 0x0)
{
throw SafeNativeMethods.Gdip.StatusException(status);
}
FontFamily[] familyArray = new FontFamily[num3];
for (int i = 0x0; i < num3; i++)
{
IntPtr ptr;
SafeNativeMethods.Gdip.GdipCloneFontFamily(new HandleRef(null, gpfamilies[i]), out ptr);
familyArray[i] = new FontFamily(ptr);
}
return familyArray;
}
}
注意如何它計算多少字體有,然後調用GdipCloneFontFamily()
爲每一個和初始化一個新FontFamily
與返回的IntPtr
。
不需要。執行FontCollection.Dispose()所做的相同事情很好。沒有。通過測試,感受更好,添加一個運行代碼10000次的按鈕。使用任務管理器查看您的程序,添加句柄,用戶對象和GDI對象列。 –