BOOL WINAPI ReadFile(
  __in         HANDLE hFile,
  __out        LPVOID lpBuffer,
  __in         DWORD nNumberOfBytesToRead,
  __out_opt    LPDWORD lpNumberOfBytesRead,
  __inout_opt  LPOVERLAPPED lpOverlapped
);BOOL WINAPI PeekNamedPipe(
  __in       HANDLE hNamedPipe,
  __out_opt  LPVOID lpBuffer,
  __in       DWORD nBufferSize,
  __out_opt  LPDWORD lpBytesRead,
  __out_opt  LPDWORD lpTotalBytesAvail,
  __out_opt  LPDWORD lpBytesLeftThisMessage
);        //Takes in a device path and opens a handle to the device.
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern SafeFileHandle CreateFile(
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode, 
            IntPtr lpSecurityAttributes, 
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes, 
            IntPtr hTemplateFile);//Uses a handle (created with CreateFile()), and lets us read USB data from the device.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool ReadFile(
            SafeFileHandle hFile,
            IntPtr lpBuffer,
            uint nNumberOfBytesToRead,
            ref uint lpNumberOfBytesRead,
            IntPtr lpOverlapped);        //Copies data from a named or anonymous pipe into a buffer without removing it from the pipe. It also returns information about data in the pipe.
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool PeekNamedPipe(
            SafeFileHandle hFile,
            IntPtr lpBuffer,
            uint nBufferSize,
            ref uint lpBytesRead,
            ref uint lpTotalBytesAvail,
            ref uint lpBytesLeftThisMessage
            );SafeFileHandle ReadHandleToUSBDevice = null;
ReadHandleToUSBDevice = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
在一个后台进程内调用ReadFile读取USB管道数据会因为没有可供读取的数据而发生阻塞。我尝试先调用PeekNamedPipe以检测是否有数据可供读取,可能是因为方法声明是数据类型定义错误,ErrorStatus = (uint)Marsha.l.GetLastWin32Error();总是返回1或者1008。请问:是否可以使用PeekNamedPipe检测读取缓冲区大小,或者需要采用其他方法?

解决方案 »

  1.   

    我发现可以使用new FileStream(WriteHandleToUSBDevice, FileAccess.Read)来读取数据,然则,还是不允许检测是否可读取,不允许设定超时。
      

  2.   

    http://www.koders.com/csharp/fid41608AA1B5092296391FEBDE3F4B4FD1EE9A995D.aspx?s=datagrid
      

  3.   


    请问使用SafeFileHandle 可以吗?我现在用SafeFileHandle 形式的声明总是返回0,GetLastError为1。        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            static extern bool PeekNamedPipe(
                SafeFileHandle handle,
                byte[] buffer, 
                uint nBufferSize, 
                ref uint bytesRead,
                ref uint bytesAvail,
                ref uint BytesLeftThisMessage);
      

  4.   

    我改用 xingyuebuyu 提供的类,来创建管道,仍然是可以正常读写不可以调用PeekNamedPipe获得输入缓冲可用字节数,LastError == 1.
    我尝试使用@"E:\p.txt"作为路径效果一样,可见不是管道的问题???
      

  5.   

    http://msdn.microsoft.com/en-us/library/aa365779(VS.85).aspxhttp://msdn.microsoft.com/en-us/library/aa365779(VS.85).aspxNote  The PeekNamedPipe function can block thread execution the same way any I/O function can when called on a synchronous handle in a multi-threaded application. To avoid this condition, use a pipe handle created for asynchronous I/O.在多线程中同步IO调用时PeekNamedPipe 会阻塞线程的运行,需要使用异步IO.ReadHandleToUSBDevice = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_FLAG_OVERLAPPED, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
      

  6.   


    恕我愚钝,
    我确实没有注意到这段话。
    即使现在终于看到也还是不能理解。我理解的是如果句柄是同步模式的,且有多个线程使用该句柄,PeekNamedPipe 将阻塞除非其他方法已返回。我调试的时候,读取的句柄是PeekNamedPipe 独享的(有一个写入句柄,已经实践证明不打开写入句柄效果一样),在我的测试环境中,PeekNamedPipe 立即返回了0,并SetLastError = 1。
      

  7.   

    把PeekNamedPipe和ReadFile的代码贴出来看看
      

  8.   


            public unsafe bool ReadFileManagedBuffer(SafeFileHandle hFile, byte[] buffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, IntPtr lpOverlapped)
            {
                IntPtr pINBuffer = IntPtr.Zero;            try
                {
                    pINBuffer = Marshal.AllocHGlobal((int)nNumberOfBytesToRead);    //Allocate some unmanged RAM for the receive data buffer.
                      /*  
                         uint bytesRead = 0;
                         uint bytesAvail = 0;
                         uint BytesLeftThisMessage = 0;
                         if (PeekNamedPipe(hFile, pINBuffer, 1, ref bytesRead, ref bytesAvail, ref BytesLeftThisMessage))
                         { }
                         else
                         {
                             int err = Marshal.GetLastWin32Error();
                             if (err != 0)
                             {
                                 MessageBox.Show(err.ToString());
                             }
                         }
                    */
                    if (ReadFile(hFile, pINBuffer, nNumberOfBytesToRead, ref lpNumberOfBytesRead, lpOverlapped))
                    {
                        Marshal.Copy(pINBuffer, buffer, 0, (int)lpNumberOfBytesRead);    //Copy over the data from unmanged memory into the managed byte[] INBuffer
                        Marshal.FreeHGlobal(pINBuffer);
                        return true;
                    }
                    else
                    {
                        Marshal.FreeHGlobal(pINBuffer);
                        return false;
                    }            }
                catch
                {
                    if (pINBuffer != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(pINBuffer);
                    }
                    return false;
                }
            }
      

  9.   

    createfile的设置有问题
    ERROR_NO_TOKEN。确定设置了 read?share不设为0应该也有影响LZ问题的最后是怎么回事的?不过没看代码