Российский производитель и разработчик сертифицированного измерительного оборудования с 1987 года


Обнаружение ошибки в ReadData() из Lusbapi

Вы не вошли.

 Поиск | Регистрация | Вход 

Андрей
07.07.2012 16:44:56
#1

Гость

Обнаружение ошибки в ReadData() из Lusbapi

Используется модуль Е14-440.
Взаимодействие через Lusbapi.dll (версия 3.4).
Реализован алгоритм, аналогичный примеру на C++ ReadData (2 приемных буфера с поочередным переключением).

Используется потоковый сбор данных с АЦП и асинхронный режим работы функции ReadData, т.е. в поле Overlapped структуры IO_REQUEST_LUSBAPI передается указатель на OVERLAPPED.

После вызова ReadData выполняется ожидание с использованием WaitForSingleObject. Проблема состоит в том, что если во время этого ожидания (порядка неск. секунд) произойдет например физическое отключение модуля от USB порта, то WaitForSingleObject сразу же завершится (с результатом 0), а обнаружение ошибки произойдет только при очередном вызове ReadData. В результате (после завершения WaitForSingleObject) имеем не до конца наполненный буфер данных и отсутствие сообщений об ошибке (GetLastErrorInfo возвращает код 100, т.е. все нормально).

Вопрос: возможно ли обнаружение таких ошибок в асинхронном режиме работы или это принципиально невозможно ?

09.07.2012 11:56:44
#2

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: Обнаружение ошибки в ReadData() из Lusbapi

В асинхронном режиме обнаружение ошибок возможно вполне - штатными средствами WinAPI (GetOverlappedResult, GetLastError)

См. в руководстве
http://www.lcard.ru/download/e14_440_pr … _guide.pdf стр. 47

Когда Вы передаете непустой указатель на структуру OVERLAPPED, работа функции ReadData фактически сводится к вызову WinAPI ReadFile с соответствующими параметрами.
(Кстати, лично я предпочитаю не пользоваться ReadData/WriteData, а брать HANDLE h = module->GetModuleHandle() и вызывать ReadFile/WriteFile напрямую. Но это дело вкуса.)

Одного WaitForSingleObject/WaitForMultipleObjects в любом случае недостаточно.
Предлагаю такой алгоритм:

1. В структуре OVERLAPPED hEvent должно быть событие manual reset - результат вызова CreateEvent(NULL, TRUE, FALSE, NULL). Остальные поля нулевые (для устройств).

2. Если ReadFile(...) вернуло TRUE, то операция завершилась сразу (обычно для OVERLAPPED I/O так не бывает, но по документации - имеет право). Тогда берем возвращенное *lpNumberOfBytesRead и
все готово.

3. Если ReadFile(...) вернуло FALSE, но GetLastError() != ERROR_IO_PENDING, то операция завершилась сразу с ошибкой.

4. Если же ReadFile(...) вернуло FALSE и GetLastError() == ERROR_IO_PENDING, то нужно
дождаться окончания операции и получить результат завершения через GetOverlappedResult.
В простейшем случае можно просто вызвать GetOverlappedResult с параметром bWait == TRUE, но это будет ожидание без таймаута и можно повиснуть. Поэтому:

5. Делаем WaitForSingleObject с таймаутом, а если нужна возможность прервать работу, например, по команде пользователя, то заводим еще один event для отмены, который можно поднять из другого потока, и:
HANDLE wait_list[2];
wait_list[0] = my_overlapped.hEvent;
wait_list[1] = abort_event;
wait_result = WaitForMultipleObjects(2, wait_list, FALSE, timeout_ms);
switch (wait_result)...

6. Если сработало событие my_overlapped.hEvent
(case WAIT_OBJECT_0:), то переходим к шагу 8.

7. Если вышли по abort_event (case WAIT_OBJECT_0: + 1), по таймауту (case WAIT_TIMEOUT:) или произшла ошибка (default:), то прерываем операцию через CancelIo. После CancelIo ОБЯЗАТЕЛЬНО тоже делать GetOverlappedResult, т.е. следующий шаг не пропускаем.

8. Делаем GetOverlappedResult(hdev, &my_overlapped, &num_bytes, TRUE). По результату завершения этого вызова (TRUE/FALSE и GetLastError) можно судить о том, как завершилась асинхронная операция.

Примечание: с момента получения ERROR_IO_PENDING до исполнения GetOverlappedResult с bWait = TRUE нельзя трогать структуру OVERLAPPED, т.к. с ней работает ядро системы.

P.S. Вообще по работе с OVERLAPPED I/O существует много руководств, статьи MSDN и темы на форумах, в том числе в нашем форуме, например:
http://www.google.com/search?q=getoverl … e:lcard.ru