delphi应用程序冻结了整个win7系统

delphi应用程序冻结了整个win7系统,delphi,windows-7,freeze,Delphi,Windows 7,Freeze,我有一个简单的程序,可以根据每行单词的长度对文本文件进行排序 这个程序在我基于xp的旧机器上运行没有问题 现在我在我的新win7/intel core i5机器上运行这个程序,它冻结整个系统并在完成工作后恢复正常 我调查了密码,找到了导致冻结的那行 就是这一行 caption := IntToStr(i) + '..' + IntTostr(ii); 我把它改成了 caption := IntTostr(ii); //slow rate change 没有冻结 然后我把它改成了 ca

我有一个简单的程序,可以根据每行单词的长度对文本文件进行排序 这个程序在我基于xp的旧机器上运行没有问题 现在我在我的新win7/intel core i5机器上运行这个程序,它冻结整个系统并在完成工作后恢复正常

我调查了密码,找到了导致冻结的那行

就是这一行

caption := IntToStr(i) + '..' + IntTostr(ii);
我把它改成了

 caption :=   IntTostr(ii);  //slow rate change
没有冻结

然后我把它改成了

caption :=   IntTostr(i);  //fast rate change
它又结冰了

我的程序代码是

 var tword : widestring;
      i,ii,li : integer;
 begin   
     tntlistbox1.items.LoadFromFile('d:\new folder\ch.txt');
     tntlistbox2.items.LoadFromFile('d:\new folder\uy.txt');
     For ii := 15 Downto 1 Do //slow change
      Begin
        For I := 0 To TntListBox1.items.Count - 1 Do //very fast change
        Begin     
          caption := IntToStr(i) + '..' + IntTostr(ii); //problemetic line               
          tword := TntListBox1.items[i];
          LI := Length(tword);
          If lI = ii Then
          Begin             
            tntlistbox3.items.Add(Trim(tntlistbox1.Items[i]));
            tntlistbox4.items.Add(Trim(tntlistbox2.Items[i]));
          End;
        End;
      End;
    end;
知道为什么吗?如何修复它?
我使用delphi 2007/win32

这是否发生在表单的事件处理程序中?我猜是的。在这种情况下,“标题”在表单的范围内。表单的标题文本不是由VCL管理的,而是由Windows管理的,如果您在循环的每次迭代中发送新的WM_SETTEXT消息

要彻底解释为什么要这样做,需要了解Windows内部的一些知识,而我没有这些知识,但如果我要猜测一下,我会说是这样的:

每次发送带有新标题的WM_SETTEXT消息时,Windows都会进行检查,以确保它与现有标题不同。如果是,它可以立即退出。这就是为什么不频繁的更改(仅使用
ii
)不会降低系统速度的原因。但如果每次迭代都会改变,那么Windows必须执行某种任务切换才能改变它

至于为什么这会让整个系统陷入Vista内核(包括Win7)而不是XP的困境,这完全超出了我的专业范围。但如果你想把它作为某种进步的指标,有更好的方法,特别是如果这个循环看起来很紧的话


在紧密循环中处理进度更新的最佳方法是计算迭代次数,并且每X次只触发一次。(100或1000可以是X的好值,这取决于它运行的次数和整个过程的速度。)这基本上就是
ii
only选项所做的。您也可以尝试在表单上放置进度条来测量进度,而不是通过表单的标题来测量进度。

这是在表单的事件处理程序中发生的吗?我猜是的。在这种情况下,“标题”在表单的范围内。表单的标题文本不是由VCL管理的,而是由Windows管理的,如果您在循环的每次迭代中发送新的WM_SETTEXT消息

要彻底解释为什么要这样做,需要了解Windows内部的一些知识,而我没有这些知识,但如果我要猜测一下,我会说是这样的:

每次发送带有新标题的WM_SETTEXT消息时,Windows都会进行检查,以确保它与现有标题不同。如果是,它可以立即退出。这就是为什么不频繁的更改(仅使用
ii
)不会降低系统速度的原因。但如果每次迭代都会改变,那么Windows必须执行某种任务切换才能改变它

至于为什么这会让整个系统陷入Vista内核(包括Win7)而不是XP的困境,这完全超出了我的专业范围。但如果你想把它作为某种进步的指标,有更好的方法,特别是如果这个循环看起来很紧的话


在紧密循环中处理进度更新的最佳方法是计算迭代次数,并且每X次只触发一次。(100或1000可以是X的好值,这取决于它运行的次数和整个过程的速度。)这基本上就是
ii
only选项所做的。您也可以尝试在表单上放置进度条,以测量进度,而不是通过表单标题来测量进度。

更改表单标题会释放一系列操作,尤其是在Vista和Win7下的Aero active

快速尝试将使用TLabel来显示进度。差不多

Label1.caption := IntToStr(i) + '..' + IntTostr(ii); //problemetic line               
Label1.Refresh; // or Repaint
应该这样做,除非你的标签是透明的或在玻璃区域


最好遵循梅森·惠勒的建议,使用进度条。由于迭代的总次数是
15*TntListBox1.items.Count
您可以非常轻松地计算进度值。

更改表单标题会释放一系列操作,尤其是在Vista和Win7下的Aero active

快速尝试将使用TLabel来显示进度。差不多

Label1.caption := IntToStr(i) + '..' + IntTostr(ii); //problemetic line               
Label1.Refresh; // or Repaint
应该这样做,除非你的标签是透明的或在玻璃区域


最好遵循梅森·惠勒的建议,使用进度条。由于迭代的总次数是
15*TntListBox1.items.Count
您可以非常轻松地计算进度值。

首先:您忘记了tntlistbox3.items.BeginUpdate/tntlistbox3.items.EndUpdate调用(与tntlistbox4相同)

第二:

解决方案(示例):

const
UpdateInterval=500;//半秒钟
变量
...
最近更新:红衣主教;
开始
... 
LastUpdate:=GetTickCount+100000;//部队首次更新
对于ii:=15到1 Do//缓慢变化
开始
对于I:=0到TntListBox1.items.Count-1 Do//变化非常快
开始
如果(GetTickCount>(LastUpdate+UpdateInterval))或
(GetTickCount
首先:您忘记了tntlistbox3.items.BeginUpdate/tntlistbox3.items.EndUpdate调用(与tntlistbox4相同)

第二:

解决方案(示例):

const
UpdateInterval=500;//半秒钟
变量
...
最近更新:红衣主教;
开始
... 
LastUpdate:=GetTickCount+100000;//部队首次更新
对于ii:=15到1 Do//缓慢变化
开始
对于I:=0到TntListBox1.items.Count-1 Do//变化非常快
开始