Помогите разобраться с асинхронным вводом/выводом.
Задача такая: по таймеру пишу команду в плату подключенную по USB. Применяю асинхронную запись. По большому счету результат записи для меня не важен, по этому после записи жду небольшой таймаут (dwTimeOut) и возвращаю управление. А при следующей записи проверяю завершилась ли предыдущая, если нет — отменяю ее и пишу снова.
Код ф-ции записи в плату:
ULONG WriteReport(LPCVOID OutputReport,LPDWORD lpBytesWritten, DWORD dwTimeOut,
bool bRepetFind, LPDWORD lpErrorWriteFile)
{
ULONG ulResultWrite = 0,ulResult = 0;
*lpErrorWriteFile=0;
*lpBytesWritten=0;
// Если запись не завершена, завершим ееif (HasOverlappedIoCompleted((LPOVERLAPPED) &HIDOverlappedWrite) == FALSE)
{
ATLTRACE("CancelIo() - WriteReport\n");
CancelIo(hDeviceHandle);
}
ResetEvent(hEventObjectWrite);
ulResult = WriteFile
(hDeviceHandle,
OutputReport,
Capabilities.OutputReportByteLength,
lpBytesWritten,
(LPOVERLAPPED) &HIDOverlappedWrite);
ATLTRACE("WriteFile()\n");
if (!ulResult)
{
// ждём dwTimeOut
ulResultWrite = WaitForSingleObject (hEventObjectWrite, dwTimeOut);
switch (ulResultWrite)
{
case WAIT_OBJECT_0:
ulResult = GetOverlappedResult(hDeviceHandle, &HIDOverlappedWrite, lpBytesWritten, FALSE) ;
if (ulResult==1)
*lpErrorWriteFile=0;
else
*lpErrorWriteFile=GetLastError();
break;
case WAIT_TIMEOUT:
case WAIT_ABANDONED:
case WAIT_FAILED:
default:
*lpErrorWriteFile=GetLastError();
break;
}
}
return ulResult;
}
Так проблема в том, что когда я ставлю dwTimeOut<10, периодически команды до платы не доходят, а макрос HasOverlappedIoCompleted() возвращает TRUE. Если же dwTimeOut == 100, то практически все команды в плату записываются (за это время ожидания). Какое-то странное поведение
[]
Y>Так проблема в том, что когда я ставлю dwTimeOut<10, периодически команды до платы не доходят, а макрос HasOverlappedIoCompleted() возвращает TRUE. Если же dwTimeOut == 100, то практически все команды в плату записываются (за это время ожидания). Какое-то странное поведение
Посмотрите на писишной стороне USB-сниффером и на плате осциллографом. Возможно, на самом деле USB-транзакция проходит, но сама плата не способна обрабатывть слишком частые команды.
Здравствуйте, yuske, Вы писали:
Y>Помогите разобраться с асинхронным вводом/выводом.
Скажу только, что CancelIo не подходит для отмены асинхронного общения с перефирией, короче ничё она не cancel'ит. М.б. из-за этого и глюки. В общении с COM-портом я использовал SetCommState, как в USB незнаю, ищщи функцию у которой в описании сказано, что она abort делает.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Здравствуйте, quodum, Вы писали:
Q>Здравствуйте, yuske, Вы писали:
Q>[]
Y>>Так проблема в том, что когда я ставлю dwTimeOut<10, периодически команды до платы не доходят, а макрос HasOverlappedIoCompleted() возвращает TRUE. Если же dwTimeOut == 100, то практически все команды в плату записываются (за это время ожидания). Какое-то странное поведение
Q>Посмотрите на писишной стороне USB-сниффером и на плате осциллографом. Возможно, на самом деле USB-транзакция проходит, но сама плата не способна обрабатывть слишком частые команды.
Спасибо, проверю. Но команды всегда отправляются через один интервал (5 сек), а в тестах я менял только интервал ожидания результата WaitForSingleObject (hEventObjectWrite, dwTimeOut). Но насколько я понимаю вызов ф-ции WaitForSingleObject() не должен влиять на отправку асинхронной команды, или я ошибаюсь? Поток, отправляющий команду асинхронного ввода, НЕ должен находится в состоянии ожидания, пока обрабатывается отправленная (с помощью WriteFile(...)) команда. Я прав???
Здравствуйте, TarasCo, Вы писали:
TC>Все она кенсилит. Драйвер честно получит вызов Cancelation Routine, если он ее установит. А если драйвер туп — то чего от него требовать?
1. С CancelIo у меня были глюки: GetOverLappedResult после её вызова мог зависнуть, так будто я ничего не отменял. Прочитав описание к ней, я сделал вывод, что она имеет отношение только к вводу/выводу в файл из разных потоков.
2. В описании к SetCommMask (не SetCommState опечачалсо я) было как раз написано, что она отменяет все OVERLAPPED операции ввода/вывода на COM-порт. Попробовал её -- заработало и работает по сей день. Мб CancelIo и влияет на драйвер (спорить не могу т.к. в DDK никогда не лазил), но её "голос" слышан не всем, а SetCommMask понимают все (или большинство).
Т.е. я не спорю и с этого дня вместо того, чтоб рассказывать всем, о том что она не работает вообще; я буду говорить, с сылкой на тебя, что она говорит драйверу отменить I/O, но не все драйверы на это реагируют корректно, такша если глюки, надо от неё отказываться.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков