How correctlly use InternetReadFileEx() with IRF_NO_WAIT flag

drjackool 1,016 Reputation points
2026-08-22T10:20:39.21+00:00

Hi

By Wininet, currently I using InternetReadFile() in sync mode, but problem is, it is blocks some times, I want replaced it by Ex version. My question is when data is not ready and function returns should call it again in a loop or should use Sleep() function before call it again? If Sleep, how much delay?

Thanks

Windows development | Windows API - Win32

Answer accepted by question author
Taki Ly (WICLOUD CORPORATION) 4,440 Reputation points Microsoft External Staff Moderator
2026-08-24T04:10:55.19+00:00

Hello @drjackool ,

Thank you for the details. I spent some time looking into how InternetReadFileEx behaves with the IRF_NO_WAIT flag, and I would suggest avoiding both approaches you mentioned. A busy loop wastes CPU, and a Sleep()-and-retry loop is not really reliable either, since there is no correct value to sleep for. The way WinINet is meant to be used here is event-driven, so instead of guessing a delay you let the library tell you when data has arrived.

The important thing I noticed is that IRF_NO_WAIT is only meaningful on an asynchronous handle, that is, a session you opened with INTERNET_FLAG_ASYNC and for which you registered a status callback through InternetSetStatusCallback. If the handle is synchronous, the flag does not actually surface a "data not ready" state, so it does not solve the blocking you are currently seeing. On an asynchronous handle the behavior becomes what you described: when some data is already buffered the call returns TRUE with the bytes right away, and when nothing is available yet it returns FALSE with GetLastError() equal to ERROR_IO_PENDING (997).

One detail that is easy to miss is that with IRF_NO_WAIT the ERROR_IO_PENDING return does not fill your buffer. This is different from a normal asynchronous read without the flag, where the bytes are delivered into your INTERNET_BUFFERS when the completion callback fires. With IRF_NO_WAIT the callback only signals that data has arrived, so you have to issue the read again to actually retrieve it, and if you count the buffer length on that pending path you will end up over-counting. The end of the stream, by the way, is reported as TRUE with dwBufferLength equal to zero.

So rather than looping or sleeping, I would wait on an event that the callback sets when it receives INTERNET_STATUS_REQUEST_COMPLETE, and then re-issue the read. In practice the loop looks like this:

// Session in async mode, callback registered:
//   hInet = InternetOpen(..., INTERNET_FLAG_ASYNC);
//   InternetSetStatusCallback(hInet, Cb);
// Callback sets an event on INTERNET_STATUS_REQUEST_COMPLETE:
//   case INTERNET_STATUS_REQUEST_COMPLETE:
//       g_cbError = ((INTERNET_ASYNC_RESULT*)info)->dwError;
//       SetEvent(g_hComplete);

char buf[2048];
INTERNET_BUFFERSA ib;
for (;;)
{
    ZeroMemory(&ib, sizeof(ib));
    ib.dwStructSize   = sizeof(ib);
    ib.lpvBuffer      = buf;
    ib.dwBufferLength = sizeof(buf);

    if (InternetReadFileExA(hRequest, &ib, IRF_NO_WAIT, context))
    {
        if (ib.dwBufferLength == 0)
            break;                    // end of stream
        // ... consume ib.dwBufferLength bytes ...
    }
    else if (GetLastError() == ERROR_IO_PENDING)
    {
        // Data is not ready yet. Do not spin, do not Sleep.
        WaitForSingleObject(g_hComplete, INFINITE); // signaled by the callback
        if (g_cbError != ERROR_SUCCESS)
            break;                    // handle the error
        continue;                     // re-issue the read to fetch the data
    }
    else
    {
        break;                        // real error, handle GetLastError()
    }
}

If a UI thread is involved, you would normally drive the read and the re-read entirely from the callback instead of blocking on WaitForSingleObject, so that the thread stays responsive. This is also the approach the official WinINet asynchronous sample takes, where it waits on an event and continues the next read from inside the callback, without any Sleep at all, and you can find it at Windows-classic-samples.

Please let me know if it would help to adapt this directly to your current code. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

Thank you.

Was this answer helpful?

2 people found this answer helpful.
0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Taki Ly (WICLOUD CORPORATION) 4,440 Reputation points Microsoft External Staff Moderator
    2026-08-24T01:59:50.8233333+00:00

    Hi @drjackool ,

    I'm working on this issue and will try to get back to you soon. Thank you for your patience.

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.