我有一个从串口读取的程序,这是通过重叠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
}
}
使用cbInQue从ClearCommError启动dwRequestedSize。所以这是缓冲区中的字节数。在开始等待:
之前,代码还将调用具有重叠IO的WaitCommEventDWORD 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千兆字节),应用程序只使用大约50 MB的内存。因此,Pc始终具有至少2千兆字节的可用内存。
2)应用程序全天候运行,并且围绕此代码的活动非常繁重,它将发送数据或接收数据。所以我假设Windows不会选择代码或内存作为寻呼的候选者。
也许有一些我不完全理解的分页,在这种情况下你能解释一下吗。
我想我会添加一张支票来查看实际等待时间。我假设等待大约200毫秒。然后可以排除分页或其他窗口锁定的东西。因为它不太可能,它将完全相同的200毫秒。同意?我假设GetTickCount对此具有很高的精度,这将增加最少的开销。