线程更新GUI [英] Thread update GUI
问题描述
我使用Delphi已有很多年了,我记得在版本7中,甚至那时我还没有太多的知识,从那时起我就一直在使用C ++,现在我正在一家使用Delphi XE10的公司工作,并且意识到搜索我发现许多不同版本的随机物品,这让我有些困惑.
I've used the Delphi many years ago, I remember that in version 7 and even then I did not have much knowledge, I worked with C++ since then and I am currently working in a company using Delphi XE10 and realized that searching I found a lot of random things of difference versions and that makes me a little confused.
我正在使用线程,我想更新GUI并搜索,发现 Synchronize
,并且它的工作方式显示了它对性能的影响,您可以注意到应用程序冻结了
I'm playing with threads and I wanted to update the GUI and searching I found the Synchronize
and the way in which it works shows the impact it has on performance, you can notice the application freezing.
我想知道是否有一种更流畅的方式来处理此问题,例如事件,通知之类的东西?
I was wondering if there is a smoother way to handle this, something like events, notifications or whatever?
@edit
unit WriterThreadUnit;
interface
uses
System.Classes, System.SysUtils, Unit1;
type
TWriterThread = class(TThread)
private
linesToPrint: integer;
fileDirectory: string;
function generateFilename(): string;
procedure write();
protected
procedure Execute; override;
public
constructor Create
(
const createSuspended: boolean;
const linesToPrint: integer;
fileDirectory: string
);
end;
implementation
{ TWriterThread }
constructor TWriterThread.Create
(
const createSuspended: boolean;
const linesToPrint: integer;
fileDirectory: string
);
begin
Self.linesToPrint := linesToPrint;
Self.fileDirectory := fileDirectory;
Self.FreeOnTerminate := true;
inherited Create(CreateSuspended);
end;
procedure TWriterThread.Execute;
begin
inherited;
write;
end;
function TWriterThread.generateFilename: string;
begin
Result := Format('%s\%s_total_lines_%d.txt',
[
Self.fileDirectory,
FormatDateTime('hh-mm-ss-zzz', Now),
self.linesToPrint
]
);
end;
procedure TWriterThread.write;
var
fileLines: TStringList;
i: integer;
filename: string;
begin
fileLines := TStringList.Create;
filename := generateFilename;
try
for I := 1 to Self.linesToPrint do
begin
Synchronize(
procedure
begin
Form1.Memo1.Lines.Add('Writing: ' + IntToStr(I) + ' to ' + generateFilename);
end
);
fileLines.Add(Format('Line number: %d', [i]));
Sleep(1);
end;
fileLines.SaveToFile(filename);
finally
fileLines.Free;
end;
end;
end.
推荐答案
为什么不像其他人所说的那样只是尝试解决当前代码呢?您不应该每秒更新GUI数千次,您确实意识到这没有任何意义吗?但是,即使您的示例在运行时也不会冻结我的计算机上的GUI(并且我的计算机是旧的).
Why don't you just try to fix your current code as others said? You should not update GUI thousand of times per second, you do realize that this does not make any sense? However, even your example is working without freezing the GUI on my machine (and my machine is old).
这是一个示例代码,说明如何加快速度.
Here is an example code how to speed things up.
procedure TWriterThread.write;
var
fileLines, memoLines: TStringList;
i: integer;
filename: string;
procedure InternalSynchronize;
begin
Synchronize(
procedure
begin
Form1.Memo1.Lines.BeginUpdate;
Form1.Memo1.Lines.AddStrings(memoLines);
SendMessage(Form1.Memo1.Handle, EM_LINESCROLL, 0, Form1.Memo1.Lines.Count); //used to scroll down the memo
Form1.Memo1.Lines.EndUpdate;
end
);
end;
begin
fileLines := TStringList.Create;
memoLines := TStringList.Create;
filename := generateFilename;
try
for I := 1 to Self.linesToPrint do
begin
if i mod 50 = 0 then //Update GUI one per 50 writes.
InternalSynchronize;
memoLines.Clear;
memoLines.Add('Writing: ' + IntToStr(I) + ' to ' + generateFilename);
fileLines.Add(Format('Line number: %d', [i]));
end;
InternalSynchronize;
fileLines.SaveToFile(filename);
finally
fileLines.Free;
memoLines.Clear;
end;
end;
BTW: if Memo1
is flickering during update, you might consider to use DoubleBuffered property on a form.
这篇关于线程更新GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!