0

我有一个从串行端口读取的程序,这是通过重叠 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 对此将具有显着的精度,并且会增加最少的开销。

4

0 回答 0