Pergunta

Operações assíncronas com I / O Ports conclusão retornar 0 bytes transferidos, embora as operações de I / O funcionar como esperado (meus buffers de leitura se tornar completo).

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
);

No fio de trabalho:

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

Ambas as funções retornam 0 bytes em numBytes, mas buffer está enchendo. É este o comportamento esperado?

Graças.

Foi útil?

Solução

Para GetIoCompletionPort para funcionar corretamente, você precisa especificar um ponteiro não nulo a uma ULONG_PTR para ele para escrever o valor 'chave' para:

ULONG_PTR key;

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

Para usar GetOverlappedResult com sucesso, eu acredito que você precisa especificar um identificador de evento na estrutura OVERLAPPED (fortemente recomendado em qualquer caso):

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

Chamando os dois em sucessão como você estava realmente não realizar muito - ambos informá-lo sobre as mesmas coisas. Embora se você chamar tanto em sucessão, você vai precisar para mudar o evento para ser um manual-reset, alterando o terceiro parâmetro para CreateEvent para TRUE. Meu palpite é que você estava apenas tentando tanto para ver se você pode obter um para o trabalho. Todas as coisas consideradas, eu provavelmente só usar GetQueuedCompletionStatus, e deixar por isso mesmo. Claro que, normalmente você vai fazer mais do que chamam de uma vez e sair. Você normalmente chamá-lo em um loop, o processamento do buffer atual você já leu, em seguida, chamar ReadFile novamente para ler outro buffer de informações, algo como isto:

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

Pelo menos em um teste rápido na minha máquina, isso mostrou que o número de bytes lidos corretamente (sizeof(buffer) até o último pacote, então o tamanho do restante do arquivo).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top