pInvoke readFile():重叠的I / O操作正在进行中

时间:2014-07-03 11:29:56

标签: c# pinvoke

我正在尝试开发一种与电子卡通信的功能。我需要使用readFile()函数:

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

我的功能是:

EventObject = CreateEvent(IntPtr.Zero,true,true,"");
lastError = Marshal.GetLastWin32Error();

HIDOverlapped = new System.Threading.Overlapped();
HIDOverlapped.OffsetLow = 0;
HIDOverlapped.OffsetHigh = 0;
HIDOverlapped.EventHandleIntPtr = EventObject;

readHandle = CreateFile(MyDeviceInterfaceDetailData.DevicePath, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);

 uint numberOfBytesRead;
        readBuffer= new byte[8];
        string byteValue;


 bool result = ReadFile(readHandle, ref readBuffer[0], (uint)capabilities.InputReportByteLength, out numberOfBytesRead, HIDOverlapped);
 lastError = Marshal.GetLastWin32Error(); //Problem

最后一行中的函数Marshal.GetLastWin32Error()返回错误代码997.

在第二段中,代码0xc0000005(FatalExecutionEngineError)出现另一个错误,软件崩溃。

你知道我能尝试什么吗?

2 个答案:

答案 0 :(得分:4)

这是问题。

错误代码997为ERROR_IO_PENDING,这是ReadFile在开始重叠读取时将返回的内容。

来自docs

  

注意GetLastError代码ERROR_IO_PENDING不是失败;它指定读取操作异步完成等待完成。有关更多信息,请参阅备注。

说明:

  

ReadFile可能在读取操作完成之前返回。在这种情况下,ReadFile返回FALSE,GetLastError函数返回ERROR_IO_PENDING,这允许在系统完成读取操作时继续调用进程。

使用重叠I / O是一项要求吗?


如何轻松使用C#中的重叠I / O?

使用此功能定义:

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

您可以从使用Win API打开的文件中创建常规FileStream

var fileHandle = CreateFile(.....);

if (fileHandle.IsInvalid)
    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

// The last parameter of the FileStream constructor (isAsync) will make the class use async I/O
using (var stream = new FileStream(fileHandle, FileAccess.ReadWrite, 4096, true))
{
    var buffer = new byte[4096];

    // Asynchronously read 4kb
    var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
}

答案 1 :(得分:0)

直接来自MSDN

  

因为读取操作从指定的偏移量开始   OVERLAPPED结构和ReadFile可能会在之前返回   系统级读操作完成(读取待处理),既不是   偏移或结构的任何其他部分都应该被修改,释放,   或者由应用程序重用,直到事件发出信号(即,   读完了)。

如果您阅读链接页面,您会发现如果您传递除null以外的任何内容作为lpOverlapped参数,那么它将是异步调用,因此您的问题很可能来自于您尝试使用的事实在函数设置之前的readBuffer - 或换句话说:在读取完成之前。

正如Lucas已经在他的回答中指出的那样,当操作正在进行时,最后一个错误将返回997,因此这是所需的输出。