0

请参阅下面的步骤如何重现。我使用 Delphi 10.1 Berlin 和 Windows 10 并编译为 win32。

  1. 创建一个新的 VCL 表单应用程序
  2. 在表单上放置一个 TTimer 和一个 TMemo
  3. 将定时器的时间间隔设置为 10 毫秒
  4. 将此代码放入 OnTimer 事件中:
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. 运行程序

  2. 创建一个名为.txt 的文件

TMemo 输出显示:

named.txt 存在
 改名OK
  1. 现在在资源管理器中将文件renamed.txt 重命名为named.txt。

TMemo 输出现在显示:

named.txt 存在
 改名OK
named.txt 存在
 改名OK

但是会出现一条错误消息,显示“文件或文件夹不存在”。为什么?

(重命名文件返回 OK)。

将计时器的间隔设置为例如 500 毫秒似乎没问题(没有错误消息)。

这是消息(瑞典语):

图片

我什至将 exe 文件复制到另一台 PC,结果相同:

在此处输入图像描述

4

2 回答 2

1

我遇到了同样的问题,

首先:它似乎与您的代码无关。

据我所知,错误是 Windows 错误并发生,当您尝试在第一个重命名过程(窗体 Windows)正确完成之前再次重命名文件时,delphi 重命名过程可能已经完成并且您的代码继续(并开始另一个重命名)但 Windows 重命名尚未正确完成。

当您使用不同的编程语言(例如批处理文件)时,也会发生同样的问题:

:loop
    ren named.txt renamed.txt
goto loop

您会收到相同的错误消息。

要解决您的问题,我唯一能想到的就是像您在帖子中建议的那样增加计时器延迟。

我希望,这是任何帮助,我很抱歉我无法解决您的问题

于 2019-08-26T07:59:18.947 回答
0

我的猜测是计时器事件中的一行最终调用 Application.ProcessMessages (可能是添加到 Memo.Lines 属性)。如果距离定时器开始执行事件的时间已经超过 10ms,那么消息队列中将会有一个新的定时器事件等待,这将再次触发对该事件的调用。

从本质上讲,您正在执行以下语句:

  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...

一种解决方案是:

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;

确保在处理一个计时器事件时不会发生新的计时器事件。

于 2019-08-12T10:34:29.503 回答