Асинхронные операции с портами завершения ввода-вывода возвращают переданные 0 байт
-
05-07-2019 - |
Вопрос
Асинхронные операции с портами завершения ввода-вывода возвращают переданные 0 байт, хотя операции ввода-вывода работают должным образом (мои буферы чтения заполняются).
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
);
В рабочем потоке:
DWORD numBytes = 0;
LPOVERLAPPED po;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
0,
&po,
INFINITE
);
GetOverlappedResult(file, &o, &numBytes, FALSE);
Обе функции возвращают 0 байт в numBytes, но buffer
является наполняющим.Является ли это ожидаемым поведением?
Спасибо.
Решение
Для GetIoCompletionPort
для корректной работы вам необходимо указать ненулевой указатель на ULONG_PTR
чтобы он записал значение 'key' в:
ULONG_PTR key;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
&key,
&po,
INFINITE
);
Для использования GetOverlappedResult
успешно, я полагаю, вам нужно указать дескриптор события в OVERLAPPED
структура (настоятельно рекомендуется в любом случае):
o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
Вызов этих двух последовательно, как вы это делали, на самом деле мало что дает - они оба говорят вам об одних и тех же вещах.Хотя, если вы вызываете оба параметра подряд, вам нужно будет изменить Событие на ручной сброс, изменив третий параметр на CreateEvent
к ИСТИННОМУ.Я предполагаю, что вы просто пробовали и то, и другое, чтобы посмотреть, сможете ли вы заставить одно из них работать.Учитывая все обстоятельства, я бы, вероятно, просто использовал GetQueuedCompletionStatus
, и оставим все как есть.Конечно, обычно вы делаете больше, чем просто вызываете его один раз и увольняетесь.Обычно вы вызываете его в цикле, обрабатывая текущий буфер, который вы прочитали, затем вызывая ReadFile
снова, чтобы прочитать другой буфер информации, что-то вроде этого:
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);
}
По крайней мере, в быстром тестировании на моей машине это показало количество правильно прочитанных байтов (sizeof(buffer)
вплоть до последнего пакета, затем оставшийся размер файла).