2014-10-29 20 views
6

我有一個返回PrivateFontCollection功能:.NET PrivateFontCollection - 如何釋放文件鎖完成後

Public Shared Function GetCustomFonts() As PrivateFontCollection 
    Dim result = New PrivateFontCollection 

    Dim customFontFiles = {"Garamond.TTF", "Garamond-Bold.TTF", "Garamond-Italic.TTF", "EurostileExtended-Roman-DTC.TTF"} 

    For Each fontFile In customFontFiles 
     result.AddFontFile(Hosting.HostingEnvironment.MapPath("/Includes/" & fontFile)) 
    Next 

    Return result 
End Function 

我然後使用功能如下:

Using customFonts = Common.GetCustomFonts() 
    ' Do some stuff here 
End Using 

我會想到的是,文件將被釋放,但它們仍然被鎖定:我得到以下錯誤:'該操作無法完成,因爲該文件在系統中打開。關閉文件並重試。'

在IIS中關閉網站並沒有幫助;我們必須回收應用程序池才能發佈。

任何人都可以建議如何使用PrivateFontCollection這樣的文件發佈inbetween使用?

+0

我到目前爲止唯一的想法是將字體加載到內存中並使用AddMemoryFont代替。這樣我可以保證PrivateFontCollection永遠不會觸及文件。 – extremeandy 2014-10-29 23:12:14

+0

對於可能的答案看看http://stackoverflow.com/questions/26671026/how-to-delete-the-file-of-a-privatefontcollection-addfontfile – Horcrux7 2014-10-31 13:35:42

+0

添加連接錯誤https://connect.microsoft.com/ VisualStudio中/反饋/信息/ 1379843 – Peter 2015-05-29 14:00:50

回答

1

作爲一種解決方法,我將字體加載到內存中,並使用「AddMemoryFont」代替。見下面的代碼。請記住,這是我第一次在.NET中觸及非託管資源,因此我無法保證下面的內存管理是可以的。

Imports System.Drawing.Text 
Imports System.Runtime.InteropServices 

Public Class CustomFontService 
    Implements IDisposable 

    Dim _fontBuffers As List(Of IntPtr) 
    Dim _collection As PrivateFontCollection 

    Public Sub New() 
     _collection = New PrivateFontCollection 
     _fontBuffers = New List(Of IntPtr) 

     Dim customFontFiles = {"Garamond.TTF", "Garamond-Bold.TTF", "Garamond-Italic.TTF", "EurostileExtended-Roman-DTC.TTF"} 

     For Each fontFile In customFontFiles 
      Dim fontBytes = System.IO.File.ReadAllBytes(Hosting.HostingEnvironment.MapPath("/Includes/" & fontFile)) 

      Dim fontBuffer As IntPtr = Marshal.AllocHGlobal(fontBytes.Length) 
      Marshal.Copy(fontBytes, 0, fontBuffer, fontBytes.Length) 

      _fontBuffers.Add(fontBuffer) 

      _collection.AddMemoryFont(fontBuffer, fontBytes.Length) 
     Next 
    End Sub 

    Public Function GetCustomFonts() As PrivateFontCollection 
     Return _collection 
    End Function 

#Region "IDisposable Support" 
    Private disposedValue As Boolean ' To detect redundant calls 

    ' IDisposable 
    Protected Overridable Sub Dispose(disposing As Boolean) 
     If Not Me.disposedValue Then 
      If disposing Then 
       ' TODO: dispose managed state (managed objects). 
      End If 

      For Each buf In _fontBuffers 
       If (buf <> IntPtr.Zero) Then 
        Marshal.FreeHGlobal(buf) 
       End If 
      Next 

      ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below. 
      ' TODO: set large fields to null. 
     End If 
     Me.disposedValue = True 
    End Sub 

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources. 
    Protected Overrides Sub Finalize() 
     ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. 
     Dispose(False) 
     MyBase.Finalize() 
    End Sub 

    ' This code added by Visual Basic to correctly implement the disposable pattern. 
    Public Sub Dispose() Implements IDisposable.Dispose 
     ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above. 
     Dispose(True) 
     GC.SuppressFinalize(Me) 
    End Sub 
#End Region 

End Class