Как тайм-аут WaitForMultipleObjectsEx до ReadTotalTimeoutConstant?

У меня есть программа, которая читает с последовательного порта, это делается с перекрытием ввода-вывода. Я не могу понять, как может превышаться тайм-аут WaitForMultipleObjects (200 мс), когда у меня меньше тайм-аут в вызове SetCommTimeouts (100 мс). Это случается очень редко. Но когда это происходит, это часто происходит одновременно на нескольких последовательных портах. Иногда это также происходит в разных приложениях, которые используют один и тот же исходный код для связи через другой 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. Так что это количество байтов в буфере. Код также вызовет 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) Компьютеры работают только с описанным программным обеспечением, пользователь не взаимодействует с ПК и имеет много оперативной памяти (4 гигабайта). Приложение использует только около 50 Мбайт памяти. Поэтому на ПК всегда есть как минимум 2 гигабайта свободной памяти.

2) Приложение работает 24 часа в сутки, и активность этого кода очень высока: он будет либо отправлять, либо получать данные. Поэтому я предполагаю, что Windows не выберет код или память в качестве кандидата для подкачки.

Возможно, в пейджинге есть что-то, что я не до конца понимаю, и в этом случае вы можете объяснить немного больше.

Я думаю, что я добавлю проверку, чтобы увидеть, как долго фактическое ожидание. Я предполагаю, что в случае ожидания около 200 мс. тогда пейджинг или другие вещи блокировки Windows могут быть исключены. Потому что маловероятно, что это будут точно такие же 200 мс. Согласен? Я предполагаю, что GetTickCount будет иметь значительную точность для этого, и это добавит наименьшие издержки.

0 ответов

Другие вопросы по тегам