Async operations on trailing I / O ports return 0 bytes

Asynchronous I / O operations return 0 bytes, although I / O operations are working as expected (my read buffers are filling up).

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

      

In a worker thread:

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

      

Both functions return 0 bytes in numBytes, but are buffer

filled. Is this the expected behavior?

Thank.

+2


source to share


1 answer


For this to work correctly, GetIoCompletionPort

you need to provide a pointer to a non-null value for ULONG_PTR

it to write the value "key":

ULONG_PTR key;

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

      

To use GetOverlappedResult

successfully, I believe you need to specify the event handle in the structure OVERLAPPED

(highly recommended anyway):

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

      



Calling two in a row, like you, doesn't really much - they both tell you the same things. Although, if you call both in a row, you need to change the event as manual - reset by changing the third parameter CreateEvent

to TRUE. I assume you were just trying to figure out if you can get it to work. Everything considered, I would probably just use GetQueuedCompletionStatus

and leave it at that. Of course, you usually do more than call him once and walk away. You usually call it in a loop, process the current buffer that you read, and then call it again ReadFile

to read another buffer of information, something like this:

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

      

At least in a quick test on my machine, this showed the correct number of bytes read ( sizeof(buffer)

until the last packet and then the remaining file size).

+3


source







All Articles