прежде всего iocp здесь абсолютно не связано. Вы пытаетесь проверить, являются ли операции ввода-вывода (читаются в вашем случае) на дескрипторе асинхронного файла немедленным возвращением или блокированием как здесь связано iocp ? привязка iocp к файлу - единственный способ получить уведомление, когда ввод / вывод завершен. но это абсолютно не влияет на сам блок ввода / вывода или немедленный возврат. мы можем использовать любой способ уведомления здесь. (APC, IOCP или событие). для вашего теста наиболее просто использовать событие.
тогда давайте посмотрим как - как вы тестируете - читается блок или возвращается в ваш код? Вы не проверяете это вообще. проверить эту потребность после ReadFile
возврата - завершена операция или нет. операция ввода / вывода (ReadFile) завершается асинхронно - если вызов API уже возвращает вам управление, но OVERLAPPED
(IO_STATUS_BLOCK
) еще не обновлен системой, что означает, что ввод / вывод еще не завершен. OVERLAPPED
обновлены, мы можем проверить напрямую (Internal
член структуры OVERLAPPED
не STATUS_PENDING
) или по телефону GetOverlappedResult
с bWait установлено на FALSE
Если этот параметр равен FALSE
и операция еще не завершена,
функция возвращает FALSE
, а функция GetLastError
возвращает
ERROR_IO_INCOMPLETE
.
, поэтому мы можем сказать, что ReadFile
завершено асинхронно, если следующие 4 кодировки верны:
ReadFile
возврат FALSE
GetLastError()
возврат ERROR_IO_PENDING
GetOverlappedResult(.., FALSE)
возврат FALSE
GetLastError()
возврат ERROR_IO_INCOMPLETE
Вы не проверяете это в своем коде. вместо этого вы ждете, пока операция io полностью не завершится через GetOverlappedResult(.., true)
, и занимает некоторое время. и какой смысл это делать?
реальный код для теста:
void tt(PCWSTR FileName)
{
HANDLE hFile = CreateFile(FileName, FILE_GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
OVERLAPPED ov {};
if (ov.hEvent = CreateEvent(0, 0, 0, 0))
{
char buf[1024];
if (ReadFile(hFile, buf, sizeof(buf), 0, &ov))
{
DbgPrint("sync(#1)\n");
}
else
{
switch (GetLastError())
{
case ERROR_IO_PENDING:
ULONG n;
if (GetOverlappedResult(hFile, &ov, &n, FALSE))
{
DbgPrint("sync(#2)\n");
}
else
{
switch (GetLastError())
{
case ERROR_IO_INCOMPLETE:
DbgPrint("async\n");
if (!GetOverlappedResult(hFile, &ov, &n, TRUE))
{
__debugbreak();
}
break;
default: __debugbreak();
}
}
break;
default: __debugbreak();
}
}
CloseHandle(ov.hEvent);
}
CloseHandle(hFile);
}
}
обратите внимание, что результат (синхронный или нет) завершения чтения зависит от данных файла в кеше. если вы вызываете его для файла, который не был прочитан ранее (то есть данные не в кеше), возможно, API выдает «async», но если вы снова вызовете эту функцию для того же файла - вы в следующий раз быстрее всех (почти на 100%) просмотр "sync (# 2)"