如何正确关闭SafeFile句柄

时间:2013-12-29 16:17:16

标签: c# exception file-io

我正在开发一个c#项目,我在那里与USB设备进行通信。我打开连接:

[DllImport("Kernel32.dll", SetLastError = true)]
static extern Microsoft.Win32.SafeHandles.SafeFileHandle CreateFile(string filename,  [MarshalAs(UnmanagedType.U4)]FileAccess fileaccess, [MarshalAs(UnmanagedType.U4)]FileShare fileshare, int securityattributes, [MarshalAs(UnmanagedType.U4)]FileMode creationdisposition, int flags, IntPtr template);
private Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle;

...

safeFileHandle = CreateFile("\\\\.\\HsiUsb1", FileAccess.ReadWrite,FileShare.ReadWrite, 0, FileMode.Create, 0, IntPtr.Zero);

if (safeFileHandle.IsInvalid)
{
      return Marshal.GetLastWin32Error();
}
var HsiPort = new FileStream(safeFileHandle, FileAccess.ReadWrite);
if (!HsiPort.CanRead)
{
     return -1;
}

连接已关闭:

if (HsiPort != null)
{
    HsiPort.Close();                
    HsiPort = null;
}

if (safeFileHandle != null)
{
    safeFileHandle.Close();               
    safeFileHandle = null;
}

只要我同时向FileStream读取数据或从FileStream读取数据,一切都很好,我可以多次关闭并打开usb连接。但是,由于USB设备在某些事件上发送数据并且不知道发送了多少字节,因此程序将被FileStream.Read()限制。 所以我开始用FileStream.BeginRead()和EndRead()异步读取数据。一切正常,但是,当我关闭连接并再次启动时,句柄无效,获得的错误代码为5。 谁能帮我这个?如何正确关闭SafeFileHandle? 提前致谢

1 个答案:

答案 0 :(得分:2)

尝试使用using语句作为SafeFileHandle实现IDisposable的基础。

以下应该可以正常工作:

    [DllImport("Kernel32.dll", SetLastError = true)]
    static extern Microsoft.Win32.SafeHandles.SafeFileHandle CreateFile(string filename, [MarshalAs(UnmanagedType.U4)]FileAccess fileaccess, [MarshalAs(UnmanagedType.U4)]FileShare fileshare, int securityattributes, [MarshalAs(UnmanagedType.U4)]FileMode creationdisposition, int flags, IntPtr template);
    //private Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle;

    public static int doSomething()
    {
        using (var safeFileHandle = CreateFile("\\\\.\\HsiUsb1", FileAccess.ReadWrite, FileShare.ReadWrite, 0, FileMode.Create, 0, IntPtr.Zero))
        {
            if (safeFileHandle.IsInvalid)
            {
                return Marshal.GetLastWin32Error();
            }
            using (var HsiPort = new FileStream(safeFileHandle, FileAccess.ReadWrite))
            {
                if (!HsiPort.CanRead)
                {
                    return -1;
                }
            }
        }

        return 0;
    }

如果您希望稍后在另一个方法中使用文件句柄。请删除第一个使用块。然后,您必须确保在完成该文件的工作后正确处理句柄。

在你的班级中实施IDisposable并处理资源将是一种(好的)方法。