Как тайм-аут 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 будет иметь значительную точность для этого, и это добавит наименьшие издержки.