c# - SafeFileHandle.Close 抛出异常但句柄有效且有效

标签 c# wpf handle

我在 WPF 应用程序中遇到自定义游标问题。我使用以下代码创建 Cursor 对象:

[DllImport("user32.dll")]
private static extern IntPtr CreateIconIndirect(ref IconInfo icon);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);

private static Cursor CreateCursor(string cursorName, System.Drawing.Bitmap bmp, 
    int xHotspot, int yHotspot, out SafeFileHandle handle)
{
    IconInfo tmp = new IconInfo();
    GetIconInfo(bmp.GetHicon(), ref tmp);
    tmp.xHotspot = xHotspot;
    tmp.yHotspot = yHotspot;
    tmp.fIcon = false;

    IntPtr ptr = CreateIconIndirect(ref tmp);
    handle = new SafeFileHandle(ptr, true);

    if (handle.IsClosed)
    {
        return null;
    }

    Cursor cur = CursorInteropHelper.Create(handle);

    return cur;
}

当我关闭我的应用程序并且 GC 开始清理垃圾时,它会抛出一个异常:

System.Runtime.InteropServices.SEHException was unhandled
  Message=External component has thrown an exception.
  Source=mscorlib
  ErrorCode=-2147467259
  StackTrace:
       at Microsoft.Win32.Win32Native.CloseHandle(IntPtr handle)
       at Microsoft.Win32.SafeHandles.SafeFileHandle.ReleaseHandle()
       at System.Runtime.InteropServices.SafeHandle.InternalDispose()
       at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
       at System.Runtime.InteropServices.SafeHandle.Dispose()
       at System.Windows.Input.Cursor.Finalize()
  InnerException:

我通过在 if (handle.IsClosed) 上放置断点并使用即时窗口调用 handle.Close() 进行了进一步调查。一些 SafeFileHandle 的关闭很好,其他的则抛出相同的异常 — 在句柄创建后立即。

为了让事情变得有趣, Handlebars 本身也能正常工作。 IsInvalid 为假,IsClosed 为假,光标出现。只是有些句柄永远关不上。

因为我从未打算手动关闭句柄,并且它们只会在应用程序关闭时 Cursor 对象的最终确定期间关闭,所以我可以忽略它们。我没有尝试过 VS2010 之外的发布版本,我不知道这是否会导致出现崩溃对话框。但即使我可以忽略它们,它仍然很乱。

所以基本上我正在寻找任何关于这里可能出现问题的信息,在哪里尝试和调试它......一切似乎都在 native 代码或 GC 中,我无法调试它们中的任何一个。

最佳答案

您将从 CreateIconIndirect 返回的 HICON 包装在 SafeFileHandle 中,释放时调用 CloseHandleHICON 而不是所需的 DestroyIcon 上。不要将 HICON 包装在 SafeFileHandle 中,而是将其包装在自己的专用 SafeHandle 中:

class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool DestroyIcon(
        [In] IntPtr hIcon);

    private SafeIconHandle()
        : base(true)
    {
    }

    public SafeIconHandle(IntPtr hIcon)
        : base(true)
    {
        this.SetHandle(hIcon);
    }

    protected override bool ReleaseHandle()
    {
        return DestroyIcon(this.handle);
    }
}

关于c# - SafeFileHandle.Close 抛出异常但句柄有效且有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9218029/

相关文章:

c# - C# 中的非托管 dll 函数字节 * 参数返回

c# - .NET lambda 是否会阻止对其中使用的外部引用进行垃圾回收?

c# - sqlParameters vs string.Format 哪个更能提高速度?

c# - 如何在 C# WPF 中以重复模式运行 MediaPlayer?

wpf - 在 SVG 中旋转形状时保持旋转线性渐变不旋转

c# - 确定 WPF 是否可以加载图像文件的最佳方法是什么?

c# - Azure 中的 Entity Framework REST 服务 - 远程获取实体

grails - Grails复选框处理

c# MainWindowHandle 始终为零

python - 流程关闭