I need to figure out the condition when I'm ready to display the final file list in a ListView after a series of FindNextChangeNotification events.
If there are multiple events coming in quick succession (e.g. both FILE_NOTIFY_CHANGE_FILE_NAME and FILE_NOTIFY_CHANGE_SIZE), and I try to refresh my ListView with the latest file list on each of those, those multiple refreshes clash and cause errors, so I need to limit the refresh to only the last notification. But, the challenge is when to know when the last notification for that entity is complete.
For simplicity, I made my notifications Name-only, and got rid of everything else. This works for Single-Rename, Single-/Multi-Paste, and Single-/Multi-Delete. There is only 1 (Name) notification now being passed for each file in these operations, and batches work by checking for the last Name-based item in the batch only:
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
dwChangeHandles[0] = FindFirstChangeNotification(path.c_str(), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME);
dwChangeHandles[1] = FindFirstChangeNotification(path.c_str(), FALSE, FILE_NOTIFY_CHANGE_DIR_NAME);
while (TRUE) {
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, FALSE, INFINITE);
if (dwWaitStatus == WAIT_OBJECT_0) {
// A file was created, renamed or deleted in the directory.
refreshFunc();
FindNextChangeNotification(dwChangeHandles[0]);
}
else if (dwWaitStatus == WAIT_OBJECT_0 + 1) {
// A directory was created, renamed, or deleted.
refreshFunc();
FindNextChangeNotification(dwChangeHandles[1]);
}
Refresh Func will also check for batch operations using global variables:
if (batchOperation) {
batchOperationCurrentCount--;
if (batchOperationCurrentCount == 0) {
batchOperation = false; // Reset batchOperation flag
ContentsListView_Refresh(); // Ready to refresh
}
}
else {
// Not a batch operation (e.g. single Rename), refresh immediately
ContentsListView_Refresh();
}
But, there is one case that doesn't work: When I save a new non-empty file from an external application, there are 2 File-Name notifications being sent for the same file. If I open Notepad and type a new file and then Save As for the first time in that directory, I get a double File-Name notification that I have to process. Not sure why that is, maybe because creating and renaming both happen in that scenario and both correspond to a FILE_NOTIFY_CHANGE_FILE_SIZE? It's not a directory notification, it's specifically a double File one.
If I were to add FILE_NOTIFY_CHANGE_FILE_SIZE notifications on top, all those notifications would increase further. The Rename/Paste/Delete would double to 2, and this Create New File would grow to 3 notifications.
So, how do I know when I'm done? Do I need a fixed timer to check, or a queue to sequentially execute the refresh?
I would prefer to use this FindFirstFile... approach as opposed to ReadDirectoryChangesW.
-
2I guess you need to pick a refresh time that makes sense, say 500ms or 1 second. When you get a change notification, start the timer. If you get another change notification before the timer elapses, restart it. Otherwise do your refresh when the timer goes off.Jonathan Potter– Jonathan Potter2025年11月03日 02:15:26 +00:00Commented Nov 3 at 2:15
-
Yes, that's what I'll do. Thanksgene b.– gene b.2025年11月03日 14:09:27 +00:00Commented Nov 3 at 14:09