如何从第二个线程更新进度指示器?

5

我有一个带有进度指示器的主表单。在数据模块中,我有十个数据集,每个数据集都定义了OnBeforeOpen事件。

我想通过主表单上的进度条显示已打开数据集的进度百分比。

由于我完全不懂多线程编程,请问有人可以给我一些建议吗?

非常感谢。


请参阅Delphi - Synchronize Thread with Frame。这似乎是您问题的重复。提供了一个使用PostMessage()的示例。 - LU RD
OTL在这里有什么作用?目前,您描述的不是单线程程序,而只是一个静态的、暂停在断点上的程序。您有一个静态状态并希望显示它。好吧,有很多选择,从Application.OnIdle开始。如果您确定有一些非常特殊的条件需要将多线程概念融入问题中,那么也许您可以透露一些关于您的程序、其整体设计和源代码的信息。http://www.catb.org/esr/faqs/smart-questions.html目前您的问题中没有关于多线程的内容,只是关于简单的单线程应用程序。 - Arioch 'The
2
为什么需要线程?只需在“OnBeforeOpen”事件中更新进度指示器即可。 - kobik
1个回答

11

要么从线程中发布一条消息到主线程并在那里更新进度条,要么使用TThread.Queue方法在主线程的上下文中执行一些代码。

unit Unit12;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;

const
  WM_UPDATE_PB = WM_USER;

type
  TForm12 = class(TForm)
    ProgressBar1: TProgressBar;
    ProgressBar2: TProgressBar;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  public
    procedure WMUpdatePB(var msg: TMessage); message WM_UPDATE_PB;
  end;

var
  Form12: TForm12;

implementation

{$R *.dfm}

procedure UpdateFromThreadViaMessage;
var
  i: integer;
begin
  for i := 1 to 100 do begin
    Sleep(20);
    PostMessage(Form12.Handle, WM_UPDATE_PB, i, 0);
  end;
end;

procedure UpdateFromThreadViaQueue;
var
  i: integer;
begin
  for i := 1 to 100 do begin
    Sleep(20);
    TThread.Queue(nil,
      procedure begin
        Form12.ProgressBar2.Position := i;
      end);
  end;
end;

procedure TForm12.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(UpdateFromThreadViaMessage).Start;
  TThread.CreateAnonymousThread(UpdateFromThreadViaQueue).Start;
end;

procedure TForm12.WMUpdatePB(var msg: TMessage);
begin
  ProgressBar1.Position := msg.WParam;
end;

end.

谢谢:最终我使用了UpdateFromThreadViaQueue,它运行得非常好。我选择了你的答案,因为它帮助我理解了线程消息和线程队列的工作原理。在研究了你的答案以及对我的问题的所有其他答案之后,我现在可以理解为什么在这种特定情况下不需要使用线程。 - Fabio Vitale
@Fabio OTL拥有自己的消息原语,基本上使用PostMessage,但更符合OTL风格。例如http://otl.17slon.com/book/doku.php?id=book:howto:backgroundfilescanning,还有演示和OTL开发者博客文章。 - Arioch 'The
@Arioch非常感谢您指向OTL的资源:我将研究其中的例子。 - Fabio Vitale
你怎么可能不知道有OTL资源就下载并使用OTL呢? - Arioch 'The

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接