2010-05-14 23 views
2

我有一個C#項目,我使用了幾個非託管C++函數。 更確切地說,我還有靜態的IntPtr,我用它們作爲這些函數的參數。我知道,無論何時使用它們,我都應該在該類中實現IDisposable,並使用析構函數調用Dispose方法,在那裏釋放使用的IntPtr,如MSDN頁面中所述。如何在應用程序關閉時處理釋放非託管結構?

public void Dispose() 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

private void Dispose(bool disposing) 
{ 
    // Check to see if Dispose has already been called. 
    if (!this.disposed) 
    { 
     if (disposing) 
     { 
      component.Dispose(); 
     } 

     CloseHandle(m_InstanceHandle); 
     m_InstanceHandle = IntPtr.Zero; 

     disposed = true; 

    } 
} 

[System.Runtime.InteropServices.DllImport("Kernel32")] 
private extern static Boolean CloseHandle(IntPtr handle); 

但是,當我終止應用程序時,我仍然留在TaskManager中掛起的進程。我認爲,它必須與我的結構中使用的指令的MarshalAs的:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct SipxAudioCodec 
{ 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] 
     public string CodecName; 
     public SipxAudioBandwidth Bandwidth; 
     public int PayloadType; 
} 

當我創建這樣一個結構,我應該也小心地釋放它的空間使用allocs析構函數?

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct SipxAudioCodec 
{ 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] 
     public string CodecName; 
     public SipxAudioBandwidth Bandwidth; 
     public int PayloadType; 

     ~SipxAudioCodec() 
     { 
      Marshal.FreeGlobal(something...); 
     } 
} 
+0

您確定您的Dispose方法實際上是在應用程序關閉時調用的嗎? – MusiGenesis 2010-05-14 19:12:08

回答

1

處理IntPtr式的手柄中的P/Invoke互操作的正確方法是:

  • 定義從SafeHandle派生的類SafeMyHandle。它應該只覆蓋IsInvalidReleaseHandle,並且別無其他。
  • 定義另一個類MyHandle,該類具有用於該句柄的公共API的方法。
  • MyHandle應該有一個私人會員SafeMyHandle
  • MyHandle應執行IDisposable,其Dispose方法應該只需撥打SafeMyHandle.Dispose
  • 所有的p/invvoke方法都不應該直接使用IntPtr;相反,他們應該通過並返回SafeMyHandle的實例。一個例外是從「SafeMyHandle.ReleaseHandle」調用的「釋放函數」它應該採取IntPtr

如果遵循這些約定,即使您的AppDomain被粗暴地拆除,您的手柄也將被釋放。

0

我有過去在關閉後應用程序掛起的情況,通常是因爲不是所有線程都被終止。你如何終止你的應用程序?也許線程是原因?

相關問題