Delphi:在线程中分配字符串时,表格变为冻结

时间:2011-07-18 02:45:40

标签: multithreading forms delphi freeze

下面的代码在一个帖子中。

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秒

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

感谢!!!

2 个答案:

答案 0 :(得分:2)

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

SynEditLogBeginUpdate / 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 - [

答案 1 :(得分:1)

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

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