I tend to use ReadDirectoryChangesW() with an I/O Completion port, which is good for when you want to monitor multiple directories because you can have a single thread servicing the IOCP and dealing with the results from all of your calls to ReadDirectoryChangesW().
First create an IOCP, once, by calling CreateIoCompletionPort(). Start a thread that calls GetQueuedCompletionStatus() and deals with your async directory changes.
Now for each directory that you want to monitor. First open your directory handle as normal. Next associate it with your IOCP by calling CreateIoCompletionPort() and passing the IOCP handle in (see docs for more details). Finally call ReadDirectoryChangesW() and pass an OVERLAPPED as detailed in the docs. The call will return and if successful the results will become available as the results of GetQueuedCompletionStatus() in the thread that you created to service the IOCP.