Re: Monitor a directory using WaitForMultipleObjects
Igor Tandetnik wrote:
Tom Widmer [VC++ MVP] <tom_usenet@hotmail.com> wrote:
I'm not sure that's true. The docs say:
"If a change occurs after a call to FindFirstChangeNotification but
before a call to FindNextChangeNotification, the operating system
records the change. When FindNextChangeNotification is executed, the
recorded change immediately satisfies a wait for the change
notification.
Well, the interaction between FindFirst* and FindNext* is not that
important - it only happens once. The interesting interaction is between
two calls to FindNext*, which happen every time through the loop.
Agreed. There is ambiguity, but I think that one is supposed to
interpret FindNext->FindNext in the same way. That is, when
FindNextChangeNotification is called, it will immediately signal the
handle if a change has occurred since the event was last signalled. In
effect, the directory monitor saves up any changes after calling
SetEvent until FindNextChangeNotification is next called, then it
signals the event immediately.
If anything, the wording seems to indicate that you might get a false
positive the first time through, but I don't see how it may lead to
missing notifications (false positive meaning that Wait* may return
immediately even though there was no change since the last time the
files were scanned).
No missing notifications, or the function would be pretty useless.
The wording also doesn't make much sense: FindNext* is not itself a wait
operation, so what does it mean that when FindNext* is executed wait is
satisfied? What wait?
The WaitFor* call made some time after the FindNext.
FindNextChangeNotification should not be used more than once on the
same handle without using one of the wait functions. An application
may miss a change notification if it uses FindNextChangeNotification
when there is a change request outstanding."
This part agrees with my interpretation: FindNextChangeNotification sets
the handle to non-signalled, and clears the change flag. The handle will
again become signalled if a change occurs since the last call to
FindNextChangeNotification. This way, if you call
FindNextChangeNotification twice without intervening Wait, any changes
that occurred between the two calls are lost.
I think the change could be lost because of the following scenario:
FindFirstChangeNotification(h);
Wait(h);
ProcessFiles();
//file changes
FindNextChangeNotification(h);
FindNextChangeNotification(h);
Wait(h);
ProcessFiles();
I think that the first FindNext will signal h, then the second will
reset it, so the Wait(h) call blocks, and the change is missed.
Looking at your example:
HANDLE h = FindFirstChangeNotification(...);
while (Wait(h)) {
ProcessFiles();
// A new file added here
FindNextChangeNotification(h);
}
ProcessFiles misses the new file, but FindNextChangeNotification takes
the snapshot with new file already in place. The handle won't become
signalled until another change occurs, so you miss a change.
I believe the above code is fine (and you could insert a Sleep(10000)
after the ProcessFiles() call and it would still work) - the
FindNextChangeNotification will immediately signal h if a change has
occurred since the last signal, so the Wait will return without
blocking. In fact, the FindFirstChangeNotification example code in MSDN
uses the above ordering.
Since the docs aren't 100% clear, the only way to confirm the behaviour
is experimentally.
Tom