Wait on (possibly with zero timeout) overlapped.Handle
. It will be set whether the operation is completed or cancelled.
If you're already using overlapped operations, why do you need to cancel I/O at all? The entire concept of 'cancelling' an in-flight I/O operation is really race-prone, and totally subject to the underlying device stack you're trying to write to; really the only time you'd want to do this is to unblock another thread who is waiting on the completion of that I/O.
CancelIo()
works fine. I misunderstood my code.
Upon further investigation it turns out that the code was invoking CancelIo()
followed by ReadFile()
with a timeout INFINITE
. The completion port was never getting notified of the read because the remote end was never sending anything. In other words, CancelIo()
did not cancel subsequent operations.
I found some eye-opening documentation here:
Be careful when coding for asynchronous I/O because the system reserves the right to make an operation synchronous if it needs to. Therefore, it is best if you write the program to correctly handle an I/O operation that may be completed either synchronously or asynchronously. The sample code demonstrates this consideration.
It turns out that device drivers may choose to treat an asynchronous operation in a synchronous manner if the data being read is already cached by the device driver. Upon further investigation, I discovered that when CancelIo()
was being invoked before ReadFile()
it would sometimes cause the latter to return synchronously. I have no idea why the completion port was never getting notified of ReadFile()
after a CancelIo()
but I can no longer reproduce this problem.
The completion port is signaled regardless of whether ReadFile()
is synchronous or asynchronous.