繁体   English   中英

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

[英]SafeFileHandle.Close throws an exception but the handle is valid and works

我在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的关闭很好,其他人抛出相同的异常 - 在创建句柄后立即执行。

只是为了让事情变得有趣,手柄本身也很好用。 IsInvalid为false, IsClosed为false,并且显示游标。 只是有些句柄永远不会被关闭。

因为我从不打算手动关闭句柄,并且只有在应用程序关闭时完成Cursor对象的过程中才会关闭它们,我可能只能忽略它们。 我没有在VS2010之外尝试过Release版本,我不知道是否会导致出现崩溃对话框。 但即使我可以忽略它们,它仍然是凌乱的。

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

你将从CreateIconIndirect返回的HICON包装在一个SafeFileHandle中,它在释放时调用HICON上的CloseHandle而不是所需的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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM