How detect the correct modification of a file?

2019-06-07 04:22发布

问题:

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:

  1. 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)?
  2. 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.

回答1:

I know this is not a direct answer to your question, but I would recommend using ReadDirectoryChangesW rather than polling.