2014-03-03 102 views
2

我應該處理的每個字體在System.Drawing.FontFamily.Families屬性,它返回我FontFamily類,它實現IDisposable陣列?我應該處置FontFamily.Families結果嗎?

我應該處理這也實現在極少數情況下IDisposable當它們被一個屬性訪問器返回的情況下,其他任何類實例或數組?

+0

不需要。執行FontCollection.Dispose()所做的相同事情很好。沒有。通過測試,感受更好,添加一個運行代碼10000次的按鈕。使用任務管理器查看您的程序,添加句柄,用戶對象和GDI對象列。 –

回答

2

我使用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

+0

框架不應該每次都返回'FontFamily.Families'屬性的同一個實例嗎?而不是它會每次生成不同的FontFamilies的方法? – AgentFire

+0

@AgentFire你可能會想到,但是'Families'的實現每次都會重新創建它。我會將實現添加到我的答案中。 –

+0

WinForms中是否有任何有關字體資源所有權的真實文檔?一個普通的'Control'衍生物會爲其FontType屬性分配一個GDI字體資源嗎?有什麼方法可以使用它? – supercat

相關問題