我有一个从串行端口读取的程序,这是通过重叠 IO 完成的。当我在 SetCommTimeouts (100 ms) 调用中的超时时间较低时,我无法理解 WaitForMultipleObjects 如何超时 (200 ms)。它只是很少发生。但是当它发生时,它经常同时发生在多个不同的串行端口上。有时也是在不同的应用程序中使用相同的源代码在不同的 COM 端口上进行通信。
该程序将首先使用以下命令打开 com 端口:
CreateFile(szCommDevice, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
打开后它会调用 GetCommProperties 和 PurgeComm 然后:
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 100;
SetCommTimeouts(hComHandle, &timeouts);
它还在循环中开始读取端口之前调用 SetCommState 和 SetCommMask:
dwRequestedSize = dwClearError();
if( dwRequestedSize <= 0 )
dwRequestedSize = 1;
else if( dwRequestedSize > nBufferSize )
dwRequestedSize = nBufferSize;
if (!ReadFile(hComHandle, clReceived.pBuffer, dwRequestedSize , &dwRead, &osReader ))
{
DWORD dwLastError = GetLastError();
if ( dwLastError != ERROR_IO_PENDING)
{
bCloseComPort();
continue;
}
else
fWaitingOnRead = TRUE;
}
else // read completed immediately
{
if( dwRead > 0 )
{
// Add To Receive Buffer
}
}
dwRequestedSize 是从 ClearCommError 用 cbInQue 初始化的。所以这是缓冲区中的字节数。该代码还将使用重叠的 IO 调用 WaitCommEvent,然后开始等待:
DWORD dwRes = WaitForMultipleObjectsEx(2 , hEventArray, FALSE, 200 , true );
switch(dwRes)
{
// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComHandle, &osReader, &dwRead, FALSE))
{
bCloseComPort();
} // Error in communications; report it.
else // Read completed successfully.
{
if( dwRead > 0 )
{
// Add To Receive Buffer
}
}
// Reset flag so that another opertion can be issued.
fWaitingOnRead = FALSE;
break;
// Status completed
case WAIT_OBJECT_0 + 1:
if (!GetOverlappedResult(hComHandle, &osStatus, &dwOvRes, FALSE))
{
bCloseComPort();
} // Error in communications; report it.
else
{
ReportStatusEvent(dwCommEvent);
}
fWaitingOnStat = FALSE;
break;
case WAIT_TIMEOUT:
// Why can I get here ?
break;
}
我在这里做错了吗?感谢您对此的任何意见。
一些额外的信息。
我知道分页可能是一个问题。但我还是有点不愿意接受,有两个原因。
1) 计算机只运行所描述的软件,没有用户与 PC 的交互,它有大量的 RAM(4 Giga 字节),应用程序只使用大约 50 MB 的内存。因此,PC 始终至少有 2 Giga 字节的空闲内存。
2) 应用程序 24/7 全天候运行,围绕此代码的活动非常繁重,它将发送数据或接收数据。所以我假设windows不会选择代码或内存作为分页的候选者。
也许有一些关于寻呼的东西我不完全理解,在这种情况下你能解释一下吗?
我想我会添加一个检查来查看实际等待的时间。我假设如果等待大约 200 毫秒。然后可以排除分页或其他窗口锁定的东西。因为不太可能是完全相同的 200 毫秒。同意?我认为 GetTickCount 对此将具有显着的精度,并且会增加最少的开销。