线程更新GUI [英] Thread update GUI

查看:72
本文介绍了线程更新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:如果 Memo1 在更新过程中闪烁,则可以考虑使用

BTW: if Memo1 is flickering during update, you might consider to use DoubleBuffered property on a form.

这篇关于线程更新GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆