【问题标题】:Delphi - Synchronize Thread with FrameDelphi - 将线程与帧同步
【发布时间】:2011-03-13 14:46:33
【问题描述】:

下午好 :-), 我有一个框架。这个Frame是我用Main Form动态创建的。

主要形式:

Interface := TInterface.Create(self);
    with handlingInterface do begin
      Parent := Form1;
      Left := 0; Top := 35;
      Width := 570; Height := 250;
    end;

在框架中我有一个线程。我从 Frame 调用这个线程。为什么我可以将 Thread 与 Frame 同步?没有:

var
Form1: TForm1;

在 Frame 中调用 Thread,并且我想更改 ProgressBar 在 Frame 中的位置。我不知道,为什么我可以在 Thread 的 Synchronize 方法中访问 ProgressBar。

如果是 Form 中的 Thread 和 ProgressBar - 同步访问是 Form1.ProgressBar ...

但我在 Frame 中有 Thread 和 ProgressBar。

【问题讨论】:

  • @Nanik:在这种情况下我的同步是什么意思?究竟什么需要同步?如果您使用 TThread 的相应成员函数,您将已经得到您想要的,因为这有效地在主线程中运行相应的代码,而不是 TThread 派生的实例。
  • 感谢评论,我编辑帖子。
  • Unit1.Form1.ProgressBar,把'Unit1'放在线程单元的实现部分的uses子句中。或者,这是一个长镜头?
  • 谢谢 :-),但是 ProgressBar 在 Frame 上,这是个问题。
  • 您可以在创建线程时将框架的引用提供给线程,并在需要更新进度条时使用它。

标签: multithreading delphi forms frame


【解决方案1】:

如果您只想从线程中更新进度条,则有一个更轻量级的选项。我会考虑改用 PostMessage 。无论如何,您不希望您的线程对框架的细节了解太多。

当你创建线程时,给它你框架的句柄,这样它就知道在哪里发布消息。让框架侦听包含进度位置的 Windows 消息,并更新进度条。

这是一个非常简单的示例,它将进度条从 0 增加到 100,每次增量之间有短暂的睡眠:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

const
  WM_PROGRESS_MESSAGE = WM_USER + 99;

type
  TProgressThread = class(TThread)
  private
    FWindowHandle: HWND;
  protected
    procedure Execute; override;
  public
    property WindowHandle: HWND read FWindowHandle write FWindowHandle;
  end;

  TFrame2 = class(TFrame)
    ProgressBar1: TProgressBar;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure OnProgressMessage(var Msg: TMessage); message WM_PROGRESS_MESSAGE;
  public
  end;

implementation

{$R *.dfm}

{ TFrame2 }

procedure TFrame2.Button1Click(Sender: TObject);
var
  lThread: TProgressThread;
begin
  lThread := TProgressThread.Create(True);
  lThread.FreeOnTerminate := True;
  lThread.WindowHandle := Self.Handle;
  lThread.Start;
end;

procedure TFrame2.OnProgressMessage(var Msg: TMessage);
begin
  ProgressBar1.Position := Msg.WParam;
end;


{ TProgressThread }

procedure TProgressThread.Execute;
var
  lProgressCount: Integer;
begin
  inherited;

  for lProgressCount := 0 to 100 do
  begin
    PostMessage(FWindowHandle, WM_PROGRESS_MESSAGE, lProgressCount, 0);
    Sleep(15);
  end;
end;

end.

【讨论】:

    【解决方案2】:

    您可以在线程中引用进度条。

    示例线程类。

    unit Unit6;
    
    interface
    
    uses
        Classes, ComCtrls;
    
    type
        TProgressBarThread = class(TThread)
        private
            { Private declarations }
            FProgressBar: TProgressBar;
            procedure MoveProgress;
        protected
            procedure Execute; override;
        public
            procedure SetProgressBar(ProgressBar: TProgressBar);
        end;
    
    implementation
    
    { ProgressBarThread }
    procedure TProgressBarThread.Execute;
    begin
        { Place thread code here }
        Synchronize(MoveProgress);
    
    end;
    
    procedure TProgressBarThread.MoveProgress;
    begin
        FProgressBar.StepIt;
    end;
    
    procedure TProgressBarThread.SetProgressBar(ProgressBar: TProgressBar);
    begin
        FProgressBar := ProgressBar;
    end;
    
    end.
    

    这样使用

    var
        PBT: TProgressBarThread;
    begin
        PBT := TProgressBarThread.Create(True);
        PBT.FreeOnTerminate := True;
        PBT.SetProgressBar(ProgressBar1);
        PBT.Start;
    //  PBT.Resume;
    end;
    

    【讨论】:

    • 我知道世界上每个人都使用 TThread.Synchronize,就像它是世界上唯一的线程安全机制一样。但是在这种情况下,发布消息要好得多。
    • @Warren 我完全同意。我投票支持@Bruce 的答案。然而,我确实认为这个答案对@Nanik 有点帮助,也许是使用帖子消息的第一步。
    猜你喜欢
    • 1970-01-01
    • 2012-02-19
    • 2021-01-31
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    相关资源
    最近更新 更多