Reputation: 784
Asynchronous operations with I/O Completion Ports return 0 bytes transferred, although the I/O operations work as expected (my read buffers become full).
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 the work 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 buffer
is filling. Is this expected behaviour?
Thanks.
Upvotes: 5
Views: 2246
Reputation: 490808
For GetIoCompletionPort
to work correctly, you need to specify a non-null pointer to a ULONG_PTR
for it to write the 'key' value to:
ULONG_PTR key;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
&key,
&po,
INFINITE
);
To use GetOverlappedResult
successfully, I believe you need to specify an event handle in the OVERLAPPED
structure (strongly recommended in any case):
o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
Calling the two in succession as you were doesn't really accomplish much -- they both tell you about the same things. Though if you do call both in succession, you'll need to change the Event to be a manual-reset by changing the third parameter to CreateEvent
to TRUE. My guess is that you were just trying both to see if you could get one to work. All things considered, I'd probably just use GetQueuedCompletionStatus
, and leave it at that. Of course, you'll usually do more than call it once and quit. You normally call it in a loop, processing the current buffer you've read, then calling ReadFile
again to read another buffer of info, something like this:
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);
}
At least in a quick test on my machine, this showed the number of bytes read correctly (sizeof(buffer)
up to the last packet, then the remaining size of the file).
Upvotes: 4