How do I handle the release of unmanaged structures when the application is closed?
I have a C # project in which I am using several unmanaged C ++ functions. What's more, I also have a static IntPtr that I use as parameters for these functions. I know that whenever I use them I have to implement IDisposable in this class and use the destructor to call the Dispose method where I release the used IntPtr as stated on the MSDN page.
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);
However, when I terminate the application, I am still left hanging in the TaskManager. I believe this should be due to the use of MarshalAs statement in my structures:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SipxAudioCodec
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string CodecName;
public SipxAudioBandwidth Bandwidth;
public int PayloadType;
}
When I create a structure like this, should I also be careful to free up the space it allocates using a destructor?
[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...);
}
}
a source to share
The correct way to handle IntPtr
-style handles in p / Invoke interop is:
- Define the class
SafeMyHandle
derived fromSafeHandle
. He has only to redefineIsInvalid
andReleaseHandle
doing nothing. - Define another class
MyHandle
that has public API methods for this handle. -
MyHandle
must have a private member of the typeSafeMyHandle
. -
MyHandle
should implementIDisposable
and the methodDispose
should just be calledSafeMyHandle.Dispose
. - All p / Invoke methods should not be used
IntPtr
directly; rather, they must pass and return instancesSafeMyHandle
. The only exception is the "release function", which is called fromSafeMyHandle.ReleaseHandle
; he must acceptIntPtr
.
If you follow these conventions, your descriptors will be deallocated even if your AppDomain is rudely torn.
a source to share