Использование IOCP и ReadFileEx - PullRequest
1 голос
/ 13 марта 2012

Я играю с IOCP.Я пытаюсь написать простое приложение, которое async читает данные из файла в основном потоке.Однако я получаю ошибку (ERROR_INVALID_PARAMETER) в функции ReadFileEx, но, кажется, я делаю это хорошо.Что я делаю неправильно?Вот мой образец:

#include "stdafx.h"
#include <windows.h>
#include <assert.h>
#include <stdint.h>

VOID CALLBACK ReadCb(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,LPOVERLAPPED lpOverlapped)
{
    fprintf(stderr,"i was here\n");
}


int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE main_io,file_i;
    HANDLE file_handle;
    DWORD bytes_recvd;
    ULONG_PTR data = 0;
    OVERLAPPED overlapped;
    LPOVERLAPPED poverlapped = &overlapped;
    uint8_t read_data[1024];
    DWORD err;

    main_io = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    assert(main_io != NULL);

    file_handle = CreateFile(L"test.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED, NULL);
    assert(file_handle != INVALID_HANDLE_VALUE);

    file_i = CreateIoCompletionPort(file_handle,main_io,data,0);
    assert(file_i != NULL);

    memset(&overlapped,0,sizeof(OVERLAPPED));

    err = ReadFileEx(file_handle,(LPVOID)read_data,1024,&overlapped,ReadCb);
    fprintf(stderr,"err %d\n",GetLastError());
    assert(err != 0);

    assert(GetQueuedCompletionStatus(file_i,&bytes_recvd,&data,&poverlapped,INFINITE));

    CloseHandle(main_io);
    return 0;
}

Ответы [ 2 ]

1 голос
/ 13 марта 2012

'Если функция завершается успешно, возвращаемое значение ненулевое' - не вызывайте GetLastError () для ненулевого возврата! Переместите строку GetLastError после проверки утверждения, чтобы в случае возникновения исключения нарушения утверждения значение GetLastError не достигалось.

0 голосов
/ 14 марта 2012

Как говорит Мартин, сначала исправьте свою обработку ошибок

const BOOL result = ReadFileEx(...);

const DWORD lastError = GetLastError();

if (lastError != ERROR_SUCCESS)
{
   fprintf(stderr, "err %d\n", lastError);
}

Обратите внимание, что Мартин ошибочно полагает, что вы не должны вызывать GetLastError() для успешного возврата из ReadFileEx(), хотя этонемного особого случая ... Из документов MSDN :

При использовании ReadFileEx вы должны проверять GetLastError, даже когда функция возвращает "success", чтобы проверить наличие условий, которые "успехи ", но есть какой-то результат, о котором вы могли бы знать.Например, переполнение буфера при вызове ReadFileEx вернет TRUE, но GetLastError сообщит о переполнении с помощью ERROR_MORE_DATA.Если вызов функции успешен и нет условий предупреждения, GetLastError вернет ERROR_SUCCESS.

Но это не решает вашу проблему, это только делает ваш пример кода более корректным ...

Проблема заключается в том, что ReadFileEx() выполняет асинхронное чтение файлов с использованием процедуры завершения, а вы пытаетесь выполнить асинхронное чтение файлов с помощью порта завершения ввода / вывода.Для этого вы должны использовать ReadFile().См. этот ответ , почему я чувствую, что IOCP - лучший путь, и почему процедуры завершения немного неприятны ...

Итак, просто измените свой ReadFileEx() вызов на ReadFile() позвоните, и ваша проблема исчезнет, ​​и код опубликует завершение в IOCP, когда чтение завершится ...

ReadFile(file_handle,(LPVOID)read_data,1024,&overlapped);

, и вы закончите.

...