ReadFile does not work asynchronously on Win7 and Win2k8

According to MSDN, ReadFile can read data in two different ways: synchronously and asynchronously. I need a second one. The following code demonstrates use with an 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(); } 

In Windows XP, output: read: 1296651896 sent: 1296651896 done: 1296651899

This means that the ReadFile not blocked and returned imediatly for one second, while the reading process continued for 3 seconds. This is a normal asynchronous read.

But in Windows 7 and Windows 2008, I get the following results: read: 1296661205 sent: 1296661209 done: 1296661209. This is a synchronized read behavior.

MSDN says that async ReadFile can sometimes behave like synchronization (when a file is compressed or encrypted, for example). But the return value in this situation should be TRUE and GetLastError() == NO_ERROR. On Windows 7, I get FALSE and GetLastError() == ERROR_IO_PENDING. Therefore, WinApi informs me that this is an asynchronous call, but when I look at the test, I see that it is not!

I'm not the only one who found this “error”: read the comment on the MSDN ReadFile page.

So what is the solution? Somebody knows? 14 months after Denis found this strange behavior.

+4
source share
5 answers

I do not know the size of the file "c: \ 1.avi", but the size of the buffer that you give Windows (256 M!) Is probably large enough to hold the file. Therefore, the windows decide to read the entire file and put it in the buffer as he likes. You do not say “I want asynchronous” windows, you say “I know how to handle async”.

Just change the size of the buffer, say 1024, and your program will behave exactly the same, but will only read 1024 bytes (and also return ERROR_IO_PENDING).

In general, you do asynchrony because during the operation you want to do something else. Take a look at the sample here: Testing for the end of the file as it demonstrates an asynchronous ReadFile. If you change the sample buffer and set it to a large value, it should behave exactly like yours.

PS: I suggest you not rely on time patterns to check things, use return codes and events

+4
source

This is probably due to caching. Try to open the file without caching ( FILE_FLAG_NO_BUFFERING )

EDIT

This is actually documented in the MSDN documentation for ReadFile :

Note. If a file or device is open for asynchronous I / O, subsequent calls to functions such as ReadFiles, which are usually processed immediately, but can also behave synchronously with respect to blocked execution. See http://support.microsoft.com/kb/156932 for more information.

+1
source

According to this , I suspect that it should return TRUE in your case. But it may also be that the default parameters for the completion mode are different in different ways from Win7 / Win2k8. Try setting a different mode using SetFileCompletionNotificationModes ().

+1
source

Did you try to use the event as @Simon Mourier suggested? I know that the documentation states that the event is not required, but if you see an example in the links provided by @Simon Mourier, it uses the event for asynchronous reading.

+1
source

Windows7 / Server2008 have different behavior for resolving race conditions that may occur in GetOverlappedResultEx. When compiling for these OSs, Windows detects this and uses a different behavior. I find this evil confusing.

Here is the link: http://msdn.microsoft.com/en-us/library/dd371711(VS.85).aspx

I am sure that you have read this many times in the past, but some of the text has changed since Win7 - esp field hEvent in the OVERLAPPED structure, http://msdn.microsoft.com/en-us/library/ms684342(v = VS.85) .aspx

Functions such as GetOverlappedResult and synchronization wait functions resetauto-reset events with an inconsistent state. Therefore, you should use the manual reset event ; if you use auto-reset, your application may stop responding if you wait for the operation to complete, then call GetOverlappedResult with bWait the parameter is set to TRUE.

Could you conduct an experiment - please highlight manually reset the event in your OVERLAPPED structure instead of the auto reset event? (I do not see the highlight in your snippit - do not forget to create an event and set "hEvent" after zeroing the structure)

+1
source

Source: https://habr.com/ru/post/1338145/


All Articles