我利用各种资源拼凑了一些(多线程)代码来从串行端口读取和写入串行端口。一切正常...除了线程中从串行端口读取的循环无意中进行了繁忙的等待。本质上重复发生的是:
- 事件(在读取循环之外创建)被重置,其句柄用作 OVERLAPPED 结构中的 hEvent 成员。
- ReadFile() 传递 OVERLAPPED 结构(以及其他参数)并立即返回
- WaitForSingleObject() 等待 OVERLAPPED 结构中的事件,但总是立即返回,因为事件总是在 ReadFile() 之后设置
- GetOverlappedResult() 然后传递相同的 OVERLAPPED 结构,成功返回,但通常只读取 0 个字节
我的预期是事件的全部意义在于在有数据可供读取时发出信号。但是 ReadFile() 设置事件,那么有什么意义呢?我错过了什么?
以下精简代码演示了我系统上的问题(我连接了 COM3)。完整的代码可以很愉快地读写……但是读者会遇到上述情况:
HANDLE portHandle = CreateFile( "COM3",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL ); // succeeds
HANDLE readerEvent = CreateEvent( 0, TRUE, FALSE, _T( "Rx Event" ) ); // succeeds
char buffer[ 200 ];
DWORD bytesRead;
OVERLAPPED reader;
memset( &reader, 0, sizeof( reader ) );
reader.hEvent = readerEvent;
ResetEvent( readerEvent );
ReadFile( portHandle, buffer, 200, &bytesRead, &reader );
if ( WaitForSingleObject( reader.hEvent, 2000 ) == WAIT_OBJECT_0 )
{
// always true, never has to wait on the event.
}
最佳答案
找到它:ReadFile 函数的文档包含这一段:
- 从通信设备读取时,ReadFile 的行为由当前通信超时决定,该通信超时是使用 SetCommTimeouts 和 GetCommTimeouts 函数设置和检索的。如果未能设置超时值,可能会出现不可预测的结果。有关通信超时的详细信息,请参阅 COMMTIMEOUTS。
我根本没有使用 SetCommTimeouts()。执行 GetCommTimeouts() 并检查结果显示端口的设置是 COMMTIMEOUTS 文档中本段中描述的值:
- MAXDWORD 的值与 ReadTotalTimeoutConstant 和 ReadTotalTimeoutMultiplier 成员的零值相结合,指定读取操作将立即返回已接收到的字节,即使没有接收到字节也是如此。
关于c++ - 异步串行通信 : why does ReadFile() set the event in the OVERLAPPED struct?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22138067/