Delphi:在线程中分配字符串时表单变得冻结

发布于 2024-11-24 19:54:31 字数 370 浏览 2 评论 0原文

下面的代码位于线程中。

Tf1 := TFileStream.Create(LogsPath,fmOpenRead or fmShareDenyNone);
...
str:=TStringList.Create;
str.LoadFromStream(tf1);
...
SynEditLog.Lines.Assign(str); // I do this with Synchronize

文本文档中有 30 000 个字符串。

将这些字符串分配给 SynEdit 时,表单会被冻结。

如果逐个加载字符串,需要 40 秒...如果使用分配 - 8 秒。

如何防止这种形式的状态?

谢谢!!!

A code below is in a thread.

Tf1 := TFileStream.Create(LogsPath,fmOpenRead or fmShareDenyNone);
...
str:=TStringList.Create;
str.LoadFromStream(tf1);
...
SynEditLog.Lines.Assign(str); // I do this with Synchronize

There are 30 000 strings in a text document.

A form becomes frozen while assigning those strings to SynEdit.

If to load string by string it takes me 40 sec... If to use Assign - 8 sec.

How to prevent this form's state?

Thanks!!!

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

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

发布评论

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

评论(2

二智少女猫性小仙女 2024-12-01 19:54:31

我认为 Application.ProcessMessages 在这里根本没有帮助,因为所有工作都发生在对 Assign 的一次调用中。

SynEditLog 是否有 BeginUpdate/EndUpdate 方法?我会使用它们,看看你进展如何。例如:

SynEditLog.BeginUpdate;
try
  SynEditLog.Lines.Assign(str);
finally
  SynEditLog.EndUpdate;
end;

响应不起作用

您需要分解字符串列表到 Lines 属性的分配。像这样的东西:(

var
  LIndex: integer; 
begin
  SynEditLog.BeginUpdate;
  try
    //added: set the capacity before adding all the strings.
    SynEditLog.Lines.Capacity := str.Capacity;
    for LIndex := 0 to str.Count - 1 do
    begin
      SynEditLog.Lines.Add(str[LIndex]);
      if LIndex mod 100 = 0 then
        Application.ProcessMessages;
    end;
  finally
    SynEditLog.EndUpdate;
  end;
end;

注意:直接在浏览器中输入代码,可能无法编译)

如果这太慢,请尝试将 LIndex mod 100 = 0 增加到更大的值,例如 1000 甚至 5000。N

@

I don't think Application.ProcessMessages is going to help here at all, since all the work happens in the one call to Assign.

Does SynEditLog have BeginUpdate/EndUpdate methods? I'd use them and see how you go. For instance:

SynEditLog.BeginUpdate;
try
  SynEditLog.Lines.Assign(str);
finally
  SynEditLog.EndUpdate;
end;

In response to that not working

You'll need to break down the assignment of the string list to the Lines property. Something like this:

var
  LIndex: integer; 
begin
  SynEditLog.BeginUpdate;
  try
    //added: set the capacity before adding all the strings.
    SynEditLog.Lines.Capacity := str.Capacity;
    for LIndex := 0 to str.Count - 1 do
    begin
      SynEditLog.Lines.Add(str[LIndex]);
      if LIndex mod 100 = 0 then
        Application.ProcessMessages;
    end;
  finally
    SynEditLog.EndUpdate;
  end;
end;

(note: code typed directly into browser, may not compile)

If this is too slow, try increasing the LIndex mod 100 = 0 to something larger, like 1000 or even 5000.

N@

_畞蕅 2024-12-01 19:54:31

窗体冻结是因为您正在使用 GUI 线程向控件添加 30,000 行,这自然需要一段时间。在此期间,GUI 无法更新,因为您正在使用其线程,因此它看起来已冻结。

解决这个问题的一种方法是一次添加几行(或仅一行),并在每次添加之间更新 GUI(通过调用 Application.ProcessMessages (感谢 gordy))。

The form is freezing because you're using the GUI thread to add 30,000 lines to your control, which naturally takes a while. During this time, the GUI can't update because you're using its thread, so it looks frozen.

One way around this would be to add a few lines (or just one) at a time, and, in between each add, update the GUI (by calling Application.ProcessMessages (thanks gordy)).

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