Domanda

Le operazioni asincrone con porte di completamento I / O restituiscono 0 byte trasferiti, anche se le operazioni di I / O funzionano come previsto (i miei buffer di lettura si riempiono).

BYTE buffer[1024] = {0};
OVERLAPPED o = {0};
HANDLE file = CreateFile(
    _T("hello.txt"),
    GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL
);
HANDLE completion_port = CreateIoCompletionPort(
    file,
    NULL,
    0,
    0
);
ReadFile(
    file,
    buffer,
    1024,
    NULL,
    &o
);

Nel thread di lavoro:

DWORD numBytes = 0;
LPOVERLAPPED po;
GetQueuedCompletionStatus(
    completion_port,
    &numBytes,
    0,
    &po,
    INFINITE
);
GetOverlappedResult(file, &o, &numBytes, FALSE);

Entrambe le funzioni restituiscono 0 byte in numByte, ma buffer sta riempiendo. Questo comportamento è previsto?

Grazie.

È stato utile?

Soluzione

Affinché GetIoCompletionPort funzioni correttamente, è necessario specificare un puntatore non nullo su un ULONG_PTR affinché scriva il valore 'chiave' in:

ULONG_PTR key;

GetQueuedCompletionStatus(
    completion_port,
    &numBytes,
    &key,
    &po,
    INFINITE
);

Per utilizzare GetOverlappedResult , credo che sia necessario specificare un handle di evento nella struttura OVERLAPPED (fortemente consigliato in ogni caso):

o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);

Chiamare i due in successione così com'eri non ha molto da fare: entrambi ti raccontano le stesse cose. Tuttavia, se si chiamano entrambi in successione, è necessario modificare l'Evento in modo che venga ripristinato manualmente modificando il terzo parametro in CreateEvent su TRUE. La mia ipotesi è che stavi solo provando entrambi a vedere se riuscivi a far funzionare uno. Tutto considerato, probabilmente userò GetQueuedCompletionStatus , e lo lascerei. Certo, di solito farai più che chiamarlo una volta ed uscire. Normalmente lo chiami in un ciclo, elaborando il buffer corrente che hai letto, quindi chiamando nuovamente ReadFile per leggere un altro buffer di informazioni, qualcosa del genere:

DWORD numBytes;
LPOVERLAPPED po;
while (GetQueuedCompletionStatus(completion_port, &numBytes, &key, &po, INFINITE)) {
    std::cout << "\rRead: " << numBytes; // just to show it's set correctly.
    process(buffer);
    po->offset += sizeof(buffer);
    ReadFile(file, buffer, sizeof(buffer), NULL, po);
}

Almeno in un test rapido sulla mia macchina, questo ha mostrato il numero di byte letti correttamente ( sizeof (buffer) fino all'ultimo pacchetto, quindi le dimensioni rimanenti del file).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top