Delphi应用程序冻结整个Win7系统

im9ewurl  于 2022-09-21  发布在  其他
关注(0)|答案(3)|浏览(189)

我有一个简单的程序,根据每行字的长度对文本文件进行分类,这个程序在我基于XP的旧机器上运行没有问题,现在我在我的新Win7/英特尔酷睿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 folderch.txt');
     tntlistbox2.items.LoadFromFile('d:new folderuy.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

utugiqy6

utugiqy61#

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

要彻底解释它为什么会这样做,我需要了解Windows的内部结构,但如果我猜一猜,我会说它是这样的:

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

至于为什么这会在Vista内核(包括Win7)下使整个系统陷入困境,而不是XP,这完全超出了我的专业领域。但是,如果您试图将其作为某种进度指标,那么还有更好的方法,特别是如果这个循环像看起来那样紧密的话。

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

hm2xizp9

hm2xizp92#

更改窗体的标题会释放一大堆操作--尤其是在激活了Aero的Vista和Win7下。

一个简单的尝试是使用TLabel来显示进度。像这样的东西

Label1.caption := IntToStr(i) + '..' + IntTostr(ii); //problemetic line               
Label1.Refresh; // or Repaint

应该做到这一点,除非你的标签是透明的或在玻璃区域。

最好是听从梅森·惠勒的建议,使用进度条。因为迭代的总次数是15*TntListBox1.items.Count,所以可以很容易地计算进度值。

bxgwgixi

bxgwgixi3#

首先:您忘记了tntlistbox3.items.BeginUpdate/tntlistbox3.items.EndUpdate调用(tntlistbox4也是如此)。

第二名:Why does my program run faster if I click and hold the caption bar?

解决方案(示例):

const
  UpdateInterval = 500; // half a second
var 
  ...
  LastUpdate: Cardinal;
begin   
  ... 
  LastUpdate := GetTickCount + 100000; // forces first update
  For ii := 15 Downto 1 Do //slow change
  Begin
    For I := 0 To TntListBox1.items.Count - 1 Do //very fast change
    Begin     
      if (GetTickCount > (LastUpdate + UpdateInterval)) or
         (GetTickCount < LastUpdate) then
        caption := IntToStr(i) + '..' + IntTostr(ii); //problemetic line               
      ...
    end;
  end;

相关问题