C# 检查SafeFileHandle是否有要读取的数据

C# 检查SafeFileHandle是否有要读取的数据,c#,filestream,C#,Filestream,我正在为.NET服务对象开发一个即插即用版本的POS。我有一个FTDI设备,上面有两个设备。一个是MSR,另一个是RFID。对于快速跟进的POS For.NET,如果您给它一个硬件ID,它支持即插即用。FTDI设备的硬件ID是QUADPORT\QUAD\u SERIAL\u INTERFACE。所以在我的服务对象(所以)上,我用这个 [HardwareId("QUADPORT\\QUAD_SERIAL_INTERFACE")] [ServiceObject(DeviceType.Msr, "FT

我正在为.NET服务对象开发一个即插即用版本的POS。我有一个FTDI设备,上面有两个设备。一个是MSR,另一个是RFID。对于快速跟进的POS For.NET,如果您给它一个硬件ID,它支持即插即用。FTDI设备的硬件ID是
QUADPORT\QUAD\u SERIAL\u INTERFACE
。所以在我的服务对象(所以)上,我用这个

[HardwareId("QUADPORT\\QUAD_SERIAL_INTERFACE")]
[ServiceObject(DeviceType.Msr, "FTDI Device", "MSR FTDI Device", 1, 8)]
public class FTDIDevice : Msr
{
...
}
在open方法中,我可以查询DevicePath属性,它是正确的DevicePath。作为一个快速测试,以确保它确实通过设备路径与串行端口通信,我打开了一个指向此设备路径的文件流,然后尝试打开两个虚拟Com端口,并确保其中有足够一个“访问被拒绝”。令人惊叹的!我做的下一个测试是写入RFID设备,因为我知道大部分命令以及如何格式化字节数组以与RFID设备通信。事实上,这是我使用的代码

    public override void Open()
    {
        string str = this.DevicePath;
        handle_read = Kernel32.CreateExistingRWFile(str);
        FS_read = new FileStream(handle_read, FileAccess.ReadWrite, 9);

        Console.WriteLine("File Stream Created, Writing Open Sequence");
        byte[] open = { 0xAA, 0xBB, 0x04, 0xFB, 0x00, 0x00, 0x03, 0xF8 };
        FS_read.Write(open, 0, open.Length);

        //byte[] receive = new byte[11];
        //var something = FS_read.Read(receive, 0, receive.Length);
        //Console.WriteLine(BitConverter.ToString(receive, 0, something));
        //Close the FileStream and the SafeFileHandle
        close();
    }
    private SafeFileHandle handle_read;
    private FileStream FS_read;
第一次运行此代码时,我选择了MSR(在设备管理器和microsoft测试应用程序中有两个设备的确切名称,因此我一直在猜测),发送该命令时,MSR没有给我任何响应(很明显,这不是RFID设备)。根据MSDN站点,读取命令会一直阻塞,直到从我的流中读取至少一个字节。这是一个问题,因为MSR不响应RFID命令。所以我的程序基本上是死锁的。我强制关闭程序,然后再次启动它并选择RFID,读取方法确实返回了RFID的成功响应

所以我的问题是如何查询流以查看设备是否有响应?我尝试过使用CanRead属性(总是返回true)。我尝试使用ReadByte查看它是否会像文档所说的那样返回-1,但它也挂起了。我尝试使用Length属性,但它抛出一个异常,表示流不支持查找。我觉得我别无选择,所以我在这里问这个问题。有什么建议吗

编辑

汉斯想看看我是怎么做把手的

internal class Kernel32
{
    internal static SafeFileHandle CreateExistingRWFile(string devicePath)
    {
        return CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
    }

    internal const short FILE_ATTRIBUTE_NORMAL = 0x80;
    internal const short INVALID_HANDLE_VALUE = -1;
    internal const uint GENERIC_READ = 0x80000000;
    internal const uint GENERIC_WRITE = 0x40000000;
    internal const uint FILE_SHARE_READ = 0x00000001;
    internal const uint FILE_SHARE_WRITE = 0x00000002;
    internal const uint CREATE_NEW = 1;
    internal const uint CREATE_ALWAYS = 2;
    internal const uint OPEN_EXISTING = 3;

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool ReadFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, IntPtr lpOverlapped);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool WriteFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
}
当我看到Hans提出一些建议时,我正在从头开始工作,到目前为止,EndRead始终返回0:/

这是代码

        byte[] receive = new byte[11];
        IAsyncResult iAR = FS_read.BeginRead(receive, 0, receive.Length, ASyncFileCallBack, receive);

        byte[] wildGuess = (byte[])iAR.AsyncState;
        Console.WriteLine("Guessing:{0}", BitConverter.ToString(wildGuess));
    }
    private void ASyncFileCallBack(IAsyncResult result)
    {
        byte[] buffer = (byte[])result.AsyncState;
        int length = FS_read.EndRead(result);

        if (length > 0)
            Console.WriteLine("Response:{0}", BitConverter.ToString(buffer, 0, length));
        else
            Console.WriteLine("No Resposne");
    }

猜测
总是几乎立即吐出11个0。在控制台上显示“无响应”后不久。

FileStream.BeginRead()。非常不清楚如何获得句柄,需要在文件\u FLAG\u重叠的情况下打开它。@HansPassant请参见edit@HansPassant谢谢你的精彩表演。这有助于我打开ASYNC=true的文件流。现在,如果我在手柄上调用close,它会崩溃,出现“操作被取消”WinIO错误,这很正常,但您取消了它。使用try/catch捕获预期的异常。这也很正常,您没有再次调用BeginRead,因此没有取消任何操作。您的回调应该在有内容可读取之前运行,不可能猜测它为什么不能正常工作。如果设备名称包含单词“COM”,则改用SerialPort。