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

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

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

我的function是:

 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)出现另一个错误,软件崩溃。

你知道我能尝试什么吗?

不是问题。

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

来自文档 :

注意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); } 

直接来自MSDN :

因为读取操作从OVERLAPPED结构中指定的偏移量开始,并且ReadFile可能在系统级读取操作完成之前返回(读取挂起),所以不应修改,释放结构的偏移量或任何其他部分,或者由应用程序重用,直到事件发出信号(即读取完成)。

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

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