2012-03-13 4 views
1

Я играю с IOCP. Я пытаюсь написать простое приложение, которое async считывает данные из файла в основном потоке. Однако я получаю ошибку (ERROR_INVALID_PARAMETER) в функции ReadFileEx, но, похоже, я делаю это нормально. Что я делаю не так? Вот мой пример:Использование IOCP и 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; 
} 
+0

Вы можете использовать OVERLAPPED overlapped = {}; вместо memset (& overlapped, 0, sizeof (OVERLAPPED)); – evpo

ответ

0

Как говорит Мартин, первый исправить ошибку обработки

const BOOL result = ReadFileEx(...); 

const DWORD lastError = GetLastError(); 

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

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

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

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

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

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

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

и все готово.

+0

Спасибо, вот и все! Нашел его сам вчера, но я не смог ответить на мой вопрос из-за того, что я новый пользователь на этом сайте! – user1266334

+0

О да. Как-то я увидел «ReadFileEx», но прочитал «WSARecv»: (( –

1

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

Смежные вопросы