Асинхронный I/O
От: yuske  
Дата: 19.11.08 08:18
Оценка:
Помогите разобраться с асинхронным вводом/выводом.
Задача такая: по таймеру пишу команду в плату подключенную по 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, то практически все команды в плату записываются (за это время ожидания). Какое-то странное поведение
Re: Асинхронный I/O
От: quodum  
Дата: 19.11.08 09:20
Оценка: 2 (1) +1
Здравствуйте, yuske, Вы писали:

[]

Y>Так проблема в том, что когда я ставлю dwTimeOut<10, периодически команды до платы не доходят, а макрос HasOverlappedIoCompleted() возвращает TRUE. Если же dwTimeOut == 100, то практически все команды в плату записываются (за это время ожидания). Какое-то странное поведение


Посмотрите на писишной стороне USB-сниффером и на плате осциллографом. Возможно, на самом деле USB-транзакция проходит, но сама плата не способна обрабатывть слишком частые команды.
Re: Асинхронный I/O
От: ZAMUNDA Земля для жалоб и предложений
Дата: 19.11.08 10:12
Оценка: 2 (1)
Здравствуйте, yuske, Вы писали:

Y>Помогите разобраться с асинхронным вводом/выводом.

Скажу только, что CancelIo не подходит для отмены асинхронного общения с перефирией, короче ничё она не cancel'ит. М.б. из-за этого и глюки. В общении с COM-портом я использовал SetCommState, как в USB незнаю, ищщи функцию у которой в описании сказано, что она abort делает.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[2]: Асинхронный I/O
От: yuske  
Дата: 19.11.08 10:19
Оценка:
Здравствуйте, quodum, Вы писали:

Q>Здравствуйте, yuske, Вы писали:


Q>[]


Y>>Так проблема в том, что когда я ставлю dwTimeOut<10, периодически команды до платы не доходят, а макрос HasOverlappedIoCompleted() возвращает TRUE. Если же dwTimeOut == 100, то практически все команды в плату записываются (за это время ожидания). Какое-то странное поведение


Q>Посмотрите на писишной стороне USB-сниффером и на плате осциллографом. Возможно, на самом деле USB-транзакция проходит, но сама плата не способна обрабатывть слишком частые команды.


Спасибо, проверю. Но команды всегда отправляются через один интервал (5 сек), а в тестах я менял только интервал ожидания результата WaitForSingleObject (hEventObjectWrite, dwTimeOut). Но насколько я понимаю вызов ф-ции WaitForSingleObject() не должен влиять на отправку асинхронной команды, или я ошибаюсь? Поток, отправляющий команду асинхронного ввода, НЕ должен находится в состоянии ожидания, пока обрабатывается отправленная (с помощью WriteFile(...)) команда. Я прав???
Re[2]: Асинхронный I/O
От: TarasCo  
Дата: 19.11.08 12:50
Оценка: 2 (1)
Все она кенсилит. Драйвер честно получит вызов Cancelation Routine, если он ее установит. А если драйвер туп — то чего от него требовать?
Да пребудет с тобою сила
Re[3]: Асинхронный I/O
От: ZAMUNDA Земля для жалоб и предложений
Дата: 19.11.08 17:44
Оценка:
Здравствуйте, TarasCo, Вы писали:

TC>Все она кенсилит. Драйвер честно получит вызов Cancelation Routine, если он ее установит. А если драйвер туп — то чего от него требовать?

1. С CancelIo у меня были глюки: GetOverLappedResult после её вызова мог зависнуть, так будто я ничего не отменял. Прочитав описание к ней, я сделал вывод, что она имеет отношение только к вводу/выводу в файл из разных потоков.
2. В описании к SetCommMask (не SetCommState опечачалсо я) было как раз написано, что она отменяет все OVERLAPPED операции ввода/вывода на COM-порт. Попробовал её -- заработало и работает по сей день. Мб CancelIo и влияет на драйвер (спорить не могу т.к. в DDK никогда не лазил), но её "голос" слышан не всем, а SetCommMask понимают все (или большинство).

Т.е. я не спорю и с этого дня вместо того, чтоб рассказывать всем, о том что она не работает вообще; я буду говорить, с сылкой на тебя, что она говорит драйверу отменить I/O, но не все драйверы на это реагируют корректно, такша если глюки, надо от неё отказываться.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.