我有一个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;
}
当我创建这样的结构时,我还应该小心释放它使用析构函数分配的空间吗?
[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 :(得分:1)
在p / Invoke互操作中处理IntPtr
- 样式句柄的正确方法是:
SafeMyHandle
派生的课程SafeHandle
。它应该只覆盖IsInvalid
和ReleaseHandle
,而不执行任何其他操作。MyHandle
,该类具有该句柄的公共API的方法。MyHandle
应该有SafeMyHandle
类型的私有成员。MyHandle
应该实施IDisposable
,其Dispose
方法应该只调用SafeMyHandle.Dispose
。IntPtr
;相反,他们应该传递并返回SafeMyHandle
的实例。唯一的例外是从SafeMyHandle.ReleaseHandle
调用的“释放函数”;它应该采用IntPtr
。如果您遵循这些约定,即使您的AppDomain被严重拆除,您的句柄也会被释放。
答案 1 :(得分:0)
我曾经遇到过应用程序在关闭后挂起的情况,通常是因为并非所有线程都被终止。你如何终止你的应用程序?也许线程是原因?