c ++ - IOCP og ReadFileEx brug

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg spiller med IOCP. Jeg forsøger at skrive enkel applikation, som async læser data fra filen i hovedtråden. Men jeg får fejl (ERROR\_INVALID\_PARAMETER) i ReadFileEx-funktionen, men synes jeg gør det ok. Hvad gør jeg forkert? Her er min prøve:


#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
");
}


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
",GetLastError());
    assert(err != 0);

    assert(GetQueuedCompletionStatus(file\_i,&bytes\_recvd,&data,&poverlapped,INFINITE));

    CloseHandle(main\_io);
    return 0;
}

Bedste reference


Som Martin siger, skal du først rette op på din fejlhåndtering


const BOOL result = ReadFileEx(...);

const DWORD lastError = GetLastError();

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


Bemærk, at Martin er ukorrekt om hans antagelse om, at du ikke skal ringe GetLastError() for at få succes tilbage fra ReadFileEx(), selvom det er lidt af en særlig sag ... Fra MSDN-dokumenterne: [10]]]



  Når du bruger ReadFileEx, skal du kontrollere GetLastError, selvom
  funktion returnerer 'succes' for at kontrollere om forholdene er
  'succeser' men har noget resultat, du måske vil vide om. Til
  Eksempel, et bufferoverløb, når du ringer ReadFileEx, vender tilbage TRUE,
  men GetLastError rapporterer overløb med ERROR\_MORE\_DATA. Hvis
  funktionsopkald er vellykket, og der er ingen advarselsforhold,
  GetLastError returnerer ERROR\_SUCCESS.



Men det løser ikke dit problem, det gør din eksempels kode mere korrekt ...


Problemet er, at ReadFileEx() gør asynkron fillæsning ved hjælp af en færdiggørelsesrutine, og du forsøger at gøre asynkron fillæsning ved hjælp af en I/O-port. For det skal du bruge ReadFile(). Se dette svar for hvorfor jeg føler, at IOCP er den bedre vej at tage, og hvorfor færdiggørelsesrutinerne er lidt ubehagelige ...


Så skift simpelthen dit ReadFileEx() opkald til et ReadFile() opkald, og dit problem vil gå væk, og koden vil efterkomme IOCP'en, når læsningen fuldender ...


ReadFile(file\_handle,(LPVOID)read\_data,1024,&overlapped);


og du er færdig.

Andre referencer 1


'Hvis funktionen lykkes, er returværdien ikke-null' - ikke kald GetLastError () for et tilbagestilling uden nul! Flyt GetLastError-linjen efter bekræftelseskontrollen, så hvis GetLastError ikke finder sted .