gpt4 book ai didi

c# - 如何在应用程序关闭时处理释放非托管结构?

转载 作者:太空宇宙 更新时间:2023-11-03 14:30:11 26 4
gpt4 key购买 nike

我有一个 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...);
}
}

最佳答案

在 p/Invoke 互操作中处理 IntPtr 样式句柄的正确方法是:

  • 定义一个派生自 SafeHandle 的类 SafeMyHandle。它应该只覆盖 IsInvalidReleaseHandle,而不做任何其他事情。
  • 定义另一个类 MyHandle,它具有用于该句柄的公共(public) API 的方法。
  • MyHandle 应该有一个类型为 SafeMyHandle 的私有(private)成员。
  • MyHandle 应该实现 IDisposable,它的 Dispose 方法应该只调用 SafeMyHandle.Dispose
  • 所有的 p/Invoke 方法都不应直接使用 IntPtr;相反,它们应该传递和返回 SafeMyHandle 的实例。一个异常(exception)是从 SafeMyHandle.ReleaseHandle 调用的“释放函数”;它应该采用 IntPtr

如果您遵循这些约定,即使您的 AppDomain 被粗暴地拆除,您的句柄也会被释放。

关于c# - 如何在应用程序关闭时处理释放非托管结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2836854/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com