Delphi 在TTimer事件中重命名文件会产生错误

Delphi 在TTimer事件中重命名文件会产生错误,delphi,ttimer,Delphi,Ttimer,请参阅下面的步骤如何复制。我使用Delphi10.1和Windows10并编译到win32 创建新的VCL表单应用程序 在表单上放置TTimer和TMemo 将计时器的间隔设置为10毫秒 将此代码放入OnTimer事件中: 如果文件存在('named.txt'),则 开始 Memo1.Lines.Add('named.txt exists'); DeleteFile('rename.txt')//如果存在,请删除 如果重命名文件('named.txt','rename.txt'),则 Memo1

请参阅下面的步骤如何复制。我使用Delphi10.1和Windows10并编译到win32

  • 创建新的VCL表单应用程序
  • 在表单上放置TTimer和TMemo
  • 将计时器的间隔设置为10毫秒
  • 将此代码放入OnTimer事件中:
  • 如果文件存在('named.txt'),则
    开始
    Memo1.Lines.Add('named.txt exists');
    DeleteFile('rename.txt')//如果存在,请删除
    如果重命名文件('named.txt','rename.txt'),则
    Memo1.Lines.Add('重命名为OK')
    其他的
    Memo1.Lines.Add('rename失败,错误为:'+IntToStr(GetLastError));
    终止
    
  • 运行程序

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

  • TMemo输出显示:

    named.txt exists renamed OK named.txt已存在 改名为OK
  • 现在在资源管理器中将重命名的文件重命名回named.txt
  • TMemo输出现在显示:

    named.txt exists renamed OK named.txt exists renamed OK named.txt已存在 改名为OK named.txt已存在 改名为OK 但会出现一条错误消息,显示“文件或文件夹不存在”。为什么?

    (重命名文件返回OK)

    将计时器的间隔设置为500毫秒似乎是正常的(没有错误消息)

    以下是信息(瑞典语):

    我甚至将exe文件复制到另一台电脑上,结果相同:


    我猜计时器事件中的一行最终调用Application.ProcessMessages(可能是添加到Memo.lines属性)。如果从计时器开始执行事件起超过10毫秒,消息队列中将有一个新的计时器事件等待,这将再次触发对事件的调用

    在essense中,您将按照以下方式执行语句:

      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;
    

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

    我遇到了相同的问题

    第一:它似乎与您的代码无关

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

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

    :loop
        ren named.txt renamed.txt
    goto loop
    
    您会收到相同的错误消息

    要解决你的问题,我唯一能想到的就是按照你在帖子中的建议增加计时器延迟


    我希望,这对你有帮助,我很抱歉我不能解决你的问题

    Memo1.Lines.Add
    不能传递消息队列可能有一些事情-可能是OP没有显示的事情。否则,他所描述的似乎是不可能的。。。如果他尝试了建议的解决方案,并且解决了问题,那么肯定有什么事情发生了。@Thomas:然后发生了奇怪的事情,很可能是从外部提供的代码中发生的。如果只显示代码,您所描述的应该是不可能的。Tom无法重现该问题也支持这一点…@HeartWare:即使在程序运行时在浏览器窗口中将“重命名的.txt”重命名为“命名的.txt”,您也不能重现它吗?我一直都会遇到这个错误:@HeartWare:我同意你的反重入措施,但我认为还有更多的问题——请看我在q上的评论。用另一组文件名试试——但只在这个小测试程序中——看看你是否能重现这个问题。如果您与另一个进程处于竞争状态,那么使用其他文件名将消除来自该另一个进程的交互,并且您可以看到问题是否是可复制的。。。您的测试中可能已经有了不同的文件名(与使用的名称相比,它可能看起来是这样的)。你有没有尝试过使用这种代码?@RemyLebeau我建议不要在打开包含要处理数据的现有文件时使用
    FILE\u FLAG\u DELETE\u on\u CLOSE
    标志。为什么?使用这些标志意味着文件的所有句柄一关闭,文件就会被删除。因此,如果由于某种原因,您的应用程序崩溃,fhus无法在数据关闭后立即正确处理该数据,则该文件的打开文件句柄将关闭,文件将被删除,因此所有数据都将被删除。只有在正确处理该文件时,应用程序才应关闭该文件,而不是在。。。。。。在处理应用程序正在创建的临时文件时,使用
    文件\u标志\u删除\u关闭
    更为常见,因为它可以确保即使应用程序崩溃,它们也会被删除,因此即使是不稳定的应用程序也不会通过创建和从不删除一堆临时文件来慢慢消耗整个驱动器空间临时文件。@HeartWare:谢谢您的评论和帮助。我更改了名称,但得到了相同的错误。我甚至将exe文件复制到另一台电脑(到c:\test),并得到相同的错误:“文件或文件夹不存在”。@Thomas virusscanner如何锁定文件(当两台电脑都有相同的…)谢谢,很高兴知道至少有一个人可以重现错误。我的外行猜测,这种情况更可能发生在“快速”系统上。我的测试是在带有ssd磁盘的“高端”cpu I7-6900K上进行的。错误并不总是发生的。无论如何,重命名文件返回OK但Windows报告错误仍然让我感到困惑。再次感谢您的评论。