Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

When to call GetOverlappedResult()?

2,526 views
Skip to first unread message

nickdu

unread,
Oct 10, 2008, 7:30:01 PM10/10/08
to
In looking over the docs and sample applications on the MSDN site it's not
obvious to me under what circumstances I should be calling
GetOverlappedResult(). After some debugging I think I have the logic
correct, but I want to confirm to make sure I'm not missing any other cases.

The docs and samples seem to indicate that GetOverlappedResult() only needs
to be called when one of the API's which take an OVERLAPPED object return
FALSE and GetLastError() returns ERROR_IO_PENDING. This is how I initially
implemented things. However, this wasn't sufficient. When ReadFile()
returns FALSE and GetLastError() returns ERROR_MORE_DATA appears to be
another case where you need to call GetOverlappedResult() because the
ReadFile() call did not return the number of bytes read. Am I correct about
this? Are there any other cases in which I should be calling
GetOverlappedResult()?

--
Thanks,
Nick

nickno...@community.nospam
remove "nospam" change community. to msn.com

Jeffrey Tan[MSFT]

unread,
Oct 13, 2008, 1:52:55 AM10/13/08
to
Hi Nick,

Are you using I/O completion port in your application? There are several
ways to use I/O completion port in application. Using GetOverlappedResult()
is an old fashion way and is not recommended because it can not achieve
high multithreading performance such as scalability etc...

Below is the pseudocode of GetOverlappedResult(), as you can see it
internally uses WaitForSingleObject() API which will cause the calling
thread to block:

BOOL GetOverlappedResult(
HANDLE hfile,
OVERLAPPED* po,
PDWORD pdwNumBytes,
BOOL fWait) {

if (po->Internal == STATUS_PENDING) {
DWORD dwWaitRet = WAIT_TIMEOUT;
if (fWait) {
// Wait for the I/O to complete
dwWaitRet = WaitForSingleObject(
(po->hEvent != NULL) ? po->hEvent : hfile, INFINITE);
}

if (dwWaitRet == WAIT_TIMEOUT) {
// I/O not complete and we're not supposed to wait
SetLastError(ERROR_IO_INCOMPLETE);
return(FALSE);
}

if (dwWaitRet != WAIT_OBJECT_0) {
// Error calling WaitForSingleObject
return(FALSE);
}
}

// I/O is complete; return number of bytes transferred
*pdwNumBytes = po->InternalHigh;

if (SUCCEEDED(po->Internal)) {
return(TRUE); // No I/O error
}

// Set last error to I/O error
SetLastError(po->Internal);
return(FALSE);
}

If you are curious with GetOverlappedResult() using in I/O Completion Port,
you may refer to the articles below:
"IOCompletion Port Technique and Asynchoronos I/O Operartion"
http://www.codeproject.com/KB/IP/IOCompletionPort.aspx
"Writing Scalable Applications for Windows NT"
http://dev.rdxx.com/C/2005-9/13/202838873.shtml

A better approach is using GetQueuedCompletionStatus() API. I highly
recommend you to read "Receiving Completed I/O Request Notifications"
section of "Chapter2 Device I/O and Interthread Communication" in Jeffrey
Richter's classic book <Programming Server-Side Applications for Microsoft
Windows 2000>. This chapter is targeting the I/O completion port and talks
different ways of using it.

If I remember correct, the internet has the free download e-copy of this
book. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

nickdu

unread,
Oct 13, 2008, 8:14:00 AM10/13/08
to
I figured using completion routines was more efficient but for now I'm not
using them as I'm writing my server in .NET and going with completion
routines will add a bit more complexity. I may go that route after I get an
initial implementation working.

Regardless of which way I go I still need an answer to my original question.
And by the way, GetOverlappedResult() should not block as I pass FALSE as
the wait parameter.
--
Thanks,
Nick

nickno...@community.nospam
remove "nospam" change community. to msn.com

Jeffrey Tan[MSFT]

unread,
Oct 14, 2008, 2:42:46 AM10/14/08
to
Hi Nick,

Thank you for the feedback.

Yes, you are safe to call GetOverlappedResult(). As the pseudocode
indicates, if you pass "FALSE" to the wait parameter, its net effect is
reading OVERLAPPED.InternalHigh field(which contains the number of bytes
transferred) and then checking OVERLAPPED.Internal to determine if the I/O
operation causes any error.

Once the OVERLAPPED.Internal field indicates no I/O error, the
OVERLAPPED.InternalHigh field is valid number of bytes transferred.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support

=========================================


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.

This posting is provided "AS IS" with no warranties, and confers no rights.

nickdu

unread,
Oct 14, 2008, 8:33:01 AM10/14/08
to
That was not my question. My question is more around the docs and whether
the case I mention is another case where GetOverlappedResult() must(/should)
be called and whether there are other such cases.

In addition, I'm not checking any of the members of the OVERLAPPED
structure. GetOverlappedResult() returns the result and one of the formal
parameters is a pointer to the number of bytes transmitted.
--
Thanks,
Nick

nickno...@community.nospam
remove "nospam" change community. to msn.com

m

unread,
Oct 14, 2008, 8:57:34 PM10/14/08
to
GetOverlappedResult must be called only when you need to call it! This
unhelpful advice comes with the additional remark that need only be called
in code that looks like this psudocode

ret = ReadFile / WriteFile (hFile, ... pOverlapped) <- hEvent not NULL

if(ret == ERROR_IO_PEDING)

{

// do some work while the IO is in progress - possibly including WSFO /
WFMO on pOverlaped->hEvent

GetOverlapedResult(hFile, pOverlapped, ...)

}

This paradigm is only useful, IMHO, when you need to control IO timeouts /
cancelation in the UM app. For other situations, blocking IO or IOCP will
be more efficient by far and provide better functionality.

Look at ReadFile / WriteFile / GetOverlappedResult / CreateIoCompletionPort
in MSDN for more details

BTW: why are you using these functions in .NET? There are managed wrappers
for most things already.

"nickdu" <nickno...@community.nospam> wrote in message
news:7C82A82E-A33C-427C...@microsoft.com...

nickdu

unread,
Oct 15, 2008, 7:55:01 AM10/15/08
to
Your pseudo code matches what I say the docs indicate though they both seem
to be missing the case I mention, where ReadFile() returns TRUE and yet
bytesTransmitted is not set and therefore requiring you to call
GetOverlappedResult().

The .NET implementation you're talking about, is that
FileStream.BeginRead()/FileStream.EndRead()? If so, I'm not sure I get the
control I want from those methods. Also, the docs indicate that for anything
64K or less they are synchronous, again that might not be what I want. In
addition, I wrote a chunking stream implementation so that even for large
buffers I won't be reallocating/copying to fill up a buffer and I will stay
off the large object heap. Also, there is no managed version of
CreateNamedPipe(), WaitNamedPipe() for .NET 2.0.
--
Thanks,
Nick

nickno...@community.nospam
remove "nospam" change community. to msn.com

m

unread,
Oct 15, 2008, 7:22:13 PM10/15/08
to
In my experience, the case you mention does not occur. ReadFile usually
(always) returns failure, for handles opened as overlapped with a valid
OVERLAPPED structure passed, with a last error code of ERROR_IO_PENDING.
The value of lpNumberOfBytesRead should be valid after the operation has
completed, so if it does return success, the value should be valid
immediately. I never rely on this value in my code though and always use
the value from the OVERLAPPED structure.

Yes - FileStream.BeginRead etc. was what I was refereeing to. And you are
right in that .NET does not have any pipe classes that I know of. Creating
a custom stream implementation is probably the best thing if you need a .NET
pipe server / client for some reason.


"nickdu" <nickno...@community.nospam> wrote in message

news:7D6BD6F4-F996-4DDE...@microsoft.com...

nickdu

unread,
Oct 16, 2008, 8:38:02 AM10/16/08
to
Thanks 'm'. In the future, after I get the initial implementation working, I
will probably investigate the FileStream.BeginRead()/EndRead() route.

Just to follow up on your first statement, the case I mention does occur.
ReadFile() returns TRUE yet bytesTransferred is zero. When I call
GetOverlappedResult() that does return the correct number of bytes
transferred.

m

unread,
Oct 17, 2008, 8:35:02 PM10/17/08
to
After reviewing some code, I have found some comments from a few years ago
when I ran upaginst the same kind of problem. My solution was just to never
rely on the value of lpNumberOfBytesRead and to use GetOverlappedResult or
read it directly from the OVERLAPPED structure - BTW the usage of the
Internal & InternalHigh members is now documented in MSDN!

"nickdu" <nickno...@community.nospam> wrote in message

news:D54FC861-0FA2-416B...@microsoft.com...

0 new messages