异步串行通信:为什么ReadFile()在OVERLAPPED结构中设置事件?

时间:2014-03-03 03:16:37

标签: c++ visual-studio winapi

我已经利用各种来源将一些(多线程)代码拼凑在一起以读取和写入串行端口。一切正常......除了线程中从串口读取数据的循环无意中做了忙等待。基本上反复发生的是:

  • 重置事件(在读取循环外创建),并将其句柄用作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.
}

2 个答案:

答案 0 :(得分:2)

找到它:ReadFile函数的文档包含以下段落:

  • 从通信设备读取时,ReadFile的行为由当前设置的通信超时确定,并使用SetCommTimeouts和GetCommTimeouts函数检索。如果您未能设置超时值,则可能会出现不可预测的结果。有关通信超时的更多信息,请参阅COMMTIMEOUTS。

我根本没有使用SetCommTimeouts()。执行GetCommTimeouts()并检查结果显示端口的设置是COMMTIMEOUTS文档中本段中描述的值:

  • MAXDWORD的值与ReadTotalTimeoutConstant和ReadTotalTimeoutMultiplier成员的零值相结合,指定读取操作将立即返回已接收的字节,即使没有收到任何字节。

答案 1 :(得分:0)

您还可以使用WaitCommEvent函数等待具有特定事件掩码的事件。使用CreateFile和WaitCommEvent代码示例:Monitoring Communications Events