简体   繁体   中英

Renaming file in TTimer event produces an error

See steps below how to reproduce. I use Delphi 10.1 Berlin and Windows 10 and compile to win32.

  1. Create a new VCL Forms Application
  2. Place a TTimer and a TMemo on the form
  3. Set the timer's Interval to 10 ms
  4. Put this code in the OnTimer event:
if FileExists('named.txt') then
begin
  Memo1.Lines.Add('named.txt exists');
  DeleteFile('renamed.txt');  //delete if it exists
  if RenameFile('named.txt', 'renamed.txt') then
    Memo1.Lines.Add(' renamed OK')
  else
    Memo1.Lines.Add(' rename failed with error : '+ IntToStr(GetLastError));
end;
  1. Run the program

  2. Create a file named.txt

TMemo output shows:

named.txt exists
 renamed OK
  1. Now rename the file renamed.txt back to named.txt in the explorer.

TMemo output now shows:

named.txt exists
 renamed OK
named.txt exists
 renamed OK

But there will come an error message showing "File or folder does not exists". Why?

(Renamefile returns OK).

Setting the timer's Interval to eg 500 ms seems to be ok (no error message).

Here is the message (in Swedish):

图片

I even copied the exe-file to another PC with the same result:

在此处输入图片说明

I was experiencing the same problem,

first: it doesnt seem to have something to do with your code.

From what i figured out the error is an Windows error and occurs, when you try to rename a file again before the first rename process(form Windows) has properly finished, so the delphi rename process may have finished and your code continues(and starts another rename) but the windows rename isnt properly finished yet.

The same problem happens, when you use diffrent programming languages for example with an batch file:

:loop
    ren named.txt renamed.txt
goto loop

you get the same error message.

To fix your problem the only thing i can think of, is to increse the timer delay like you suggested in your post.

I hope, this was any help and I am very sory i coulndt solve your problem

My guess is that one of the lines in the timer event ends up calling Application.ProcessMessages (possibly the adding to the Memo.Lines property). If more than 10ms has occured from the time the timer started executing the event, there will be a new timer event waiting in the message queue, which will trigger a call to the event once again.

In essense, you are then executing statements along these lines:

  if FileExists('named.txt') then
  begin
    memo1.Lines.Add('named.txt exists');
    // Embedded ProcessMessages at some point leads to
    // the timer event being called again
    if FileExists('named.txt') then
    begin
      DeleteFile('renamed.txt');  //delete if it exists
      if RenameFile('named.txt', 'renamed.txt') then
        memo1.Lines.Add(' renamed OK')
      else
        memo1.Lines.Add(' rename failed with error : '+IntToStr(GetLastError));
    end;
    // Nested Timer Event could end here,
    // which returns execution to the outer event
    DeleteFile('renamed.txt');  //delete if it exists
    // The named.text file does not exist anymore - renamed away 7 lines above
    if RenameFile('named.txt', 'renamed.txt') then
      memo1.Lines.Add(' renamed OK')
    else
      memo1.Lines.Add(' rename failed with error : '+ IntToStr(GetLastError));
  end;
  // Original Timer event ends here...

One solution would be this:

Timer.Enabled := False;
try
  if FileExists('named.txt') then
  begin
    memo1.Lines.Add('named.txt exists');
    DeleteFile('renamed.txt');  //delete if it exists
    if RenameFile('named.txt', 'renamed.txt') then
      memo1.Lines.Add(' renamed OK')
    else
      memo1.Lines.Add(' rename failed with error : '+ IntToStr(GetLastError));
  end;
finally
  Timer.Enabled := True
end;

to make sure that no new timer events can occur while you are processing one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM