In a previous question one of my questions was how my application could know that a file has been rewritten. I should have added: "by another application". First I tried ShellNotify which reports changes in a directory but not in a specific file afaik, am I missing something?
Now I use FileAge in a timer that checks each second whether a specific file has changed. While that works it detects two modifications, about 13 ms apart; this behavior persists when I change the testing interval to 10 seconds. The code below is the callback of the timer.
procedure TAMI_Column_Selector.doWork (Sender: TObject);
var new_stamp: TDateTime;
begin
if FileAge (remove_extension (FileName) + '.csv', new_stamp) then
begin
if (new_stamp <> FDateTimeStamp) then
begin
FDateTimeStamp := new_stamp;
FTask.SyncCall (notify_user);
end; // if
end; // if
end; // doWork //
My questions:
- What exactly does cause the
notify_user
to be called twice in the code above? A dumb mistake or some strange behavior of the file system (e.g. the modification date is set on opening and on closing the file)? - It feels kind of "wasteful" to check each second whether a file has changed. Is there something like ShellNotify that notifies me only when a specific file has been modified?
Update
The answer of David Heffeman (use ReadDirectoryChangesW
instead of polling) is a correct answer for question 2. However, it leads as well to several calls during one modification (from the users point of view) as mentioned in question 1.
I compared ReadDirectoryChangesW
and the polling method. Tested with two files (0.5MB and 10 MB). In both cases the polling method was called consistently twice and the ReadDirectoryChangesW
was called several times (3 to 5 times). I'll revert to the polling method and ignore the first FileAge
change. I know I cannot be sure that this behavior will be consistent as I don't understand the mechanism causing it.
I know this is not a direct answer to your question, but I would recommend using
ReadDirectoryChangesW
rather than polling.