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

发布于 2024-09-06 00:12:42 字数 1256 浏览 5 评论 0原文

我有一个简单的程序,可以根据每行单词的长度对文本文件进行排序 这个程序在我的基于 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

i have a simple program that sorts a text file according to length of words per line
this program works without problems in my xp based old machine
now i run this program on my new win7/intel core i5 machine, it freezes whole system and back normal after it finishes it's work.

i'v invastigated the code and found the line causing the freeze

it was this specific line...

caption := IntToStr(i) + '..' + IntTostr(ii);

i'v changed it to

 caption :=   IntTostr(ii);  //slow rate change

and there is no freeze

and then i'v changed it to

caption :=   IntTostr(i);  //fast rate change

and it freeze again

my procedure code is

 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;

any idea why ? and how to fix it?
i use delphi 2007/win32

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

九歌凝 2024-09-13 00:12:42

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

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

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

至于为什么在Vista内核(包括Win7)下会导致整个系统陷入困境,而在XP下却不会,这完全超出了我的专业范围。但是,如果您尝试将其作为某种进度指示器来执行此操作,则有更好的方法,特别是当此循环像看起来一样紧密时。

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

Is this happening inside an event handler on a form? I'm going to guess taht it is. In that case, "Caption" is in the scope of the form. The form's caption text isn't managed by the VCL, but by Windows, and if you're sending a new WM_SETTEXT message on every iteration of the loop.

A thorough explanation of why this is doing what it's doing would require knowledge of Windows internals that I don't have, but if I were to take a guess, I'd say it's something like this:

Every time you send that WM_SETTEXT message with a new caption, Windows checks to make sure it's not identical to the existing caption. If it is, it can exit immediately. That's why the infrequent change (the one that only uses ii) doesn't slow your system down. But if it does change on every iteration, then Windows has to perform some sort of task switch in order to change it.

As for why that would bog down the entire system under a Vista kernel (including Win7) but not XP, that's completely outside my area of expertise. But if you're trying to do this as some sort of progress indicator, there are better ways, especially if this loop is as tight as it looks.

The best way to handle progress updates in a tight loop is to count iterations and only fire once every X times. (100 or 1000 can be good values for X, depending on how many times it's running and how fast the whole thing takes.) This is basically what the ii only option does. You could also try putting a Progress Bar on the form to measure progress instead of doing it through the form's caption.

弄潮 2024-09-13 00:12:42

更改表单的标题会释放大量操作 - 特别是在具有 Aero 活动状态的 Vista 和 Win7 下。

一个快速尝试是使用 TLabel 来代替显示进度。 类似的东西

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

除非您的标签是透明的或位于玻璃区域,否则

应该可以解决问题。最好遵循 Mason Wheeler 的建议并使用进度条。由于迭代总数为15*TntListBox1.items.Count,您可以很容易地计算进度值。

Changing a Form's caption releases a whole bunch of actions - especially under Vista and Win7 with Aero active.

A quick try would be using a TLabel instead for displaying progress. Something like

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

should do the trick unless your label is transparent or on a glass area.

It would probably be best to follow Mason Wheeler's advice and use a progressbar. As the overall number of iterations is 15*TntListBox1.items.Count you can calculate the progress value quite easily.

筑梦 2024-09-13 00:12:42

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

第二:为什么如果我单击并按住标题栏,我的程序运行得更快?解决

方案(示例):

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;

First: you forget tntlistbox3.items.BeginUpdate/tntlistbox3.items.EndUpdate calls (same for tntlistbox4).

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

Solution (example):

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文