SafeFileHandle.Close抛出异常,但句柄有效且有效

Rya*_*n P 7 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;
}
Run Code Online (Sandbox Code Playgroud)

当我关闭我的应用程序并且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:
Run Code Online (Sandbox Code Playgroud)

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

只是为了让事情变得有趣,手柄本身也很好用.IsInvalid是假的,IsClosed是假的,游标出现了.只是有些句柄永远不会被关闭.

正如我从来没有打算手动关闭手柄,他们将只定稿期间被关闭Cursor,当应用程序关闭的对象,我也许可以不理会他们.我没有在VS2010之外尝试过Release版本,我不知道是否会导致出现崩溃对话框.但即使我可以忽略它们,它仍然是凌乱的.

所以基本上我正在寻找的任何信息上什么可能在这里走错了,到哪里尝试和调试这......似乎一切都在本机代码或GC,我不能调试任何它.

ord*_*dag 16

你的包裹HICON从返回CreateIconIndirectSafeFileHandle其上发布,呼吁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);
    }
}
Run Code Online (Sandbox Code Playgroud)