Согласно MSDN, ReadFile
может считывать данные 2 разными способами: синхронно и асинхронно.
Мне нужен второй. Следующий код демонстрирует использование с OVERLAPPED
struct:
#include <windows.h>
#include <stdio.h>
#include <time.h>
void Read()
{
HANDLE hFile = CreateFileA("c:\\1.avi", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if ( hFile == INVALID_HANDLE_VALUE )
{
printf("Failed to open the file\n");
return;
}
int dataSize = 256 * 1024 * 1024;
char* data = (char*)malloc(dataSize);
memset(data, 0xFF, dataSize);
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
printf("reading: %d\n", time(NULL));
BOOL result = ReadFile(hFile, data, dataSize, NULL, &overlapped);
printf("sent: %d\n", time(NULL));
DWORD bytesRead;
result = GetOverlappedResult(hFile, &overlapped, &bytesRead, TRUE); // wait until completion - returns immediately
printf("done: %d\n", time(NULL));
CloseHandle(hFile);
}
int main()
{
Read();
}
В Windows XP вывод:
чтение: 1296651896
отправлено: 1296651896
сделано: 1296651899
Это означает, что ReadFile
не блокировался и немедленно возвращался в ту же секунду, тогда как процесс чтения продолжался в течение 3 секунд. Это нормальное асинхронное чтение.
Но на Windows 7 и Windows 2008 я получаю следующие результаты:
чтение: 1296661205
отправлено: 1296661209
сделано: 1296661209.
Это поведение синхронного чтения.
MSDN говорит, что async ReadFile
иногда может вести себя как синхронизация (например, когда файл сжат или зашифрован). Но возвращаемое значение в этой ситуации должно быть ИСТИНА и GetLastError()
== NO_ERROR.
В Windows 7 я получаю FALSE и GetLastError()
== ERROR_IO_PENDING. Поэтому WinApi говорит мне, что это асинхронный вызов, но когда я смотрю на тест, я вижу, что это не так!
Я не единственный, кто нашел эту "ошибку": прочитайте комментарий на странице ReadFile MSDN.
Так в чем же решение? Кто-нибудь знает? Прошло 14 месяцев после того, как Денис обнаружил это странное поведение.