multithreading - 如何从线程显示 "Please wait "模态表单并在工作完成后释放它?

标签 multithreading delphi modal-dialog delphi-10-seattle

我一直在努力制作一个模态表单来通知用户等待作业结束。 这是我正在尝试做的一个简单示例:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TLoader = class(TThread)
    private
      FStrings: TStrings;
      procedure ShowWait;
      procedure EndsWait;
    public
      Constructor Create(AStrings: TStrings);
      Destructor Destroy; override;
      procedure Execute; override;
  end;
var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var
  List: TStrings;
begin
  List := TStringList.Create;
  try
    // Load Some Data here
    TLoader.Create(List);
  finally
    List.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

{ TLoader }

constructor TLoader.Create(AStrings: TStrings);
begin
  inherited Create;
  FreeOnTerminate:= True;
  FStrings:= TStringList.Create;
  FStrings.AddStrings(AStrings);
end;

destructor TLoader.Destroy;
begin
  FStrings.Free;
  inherited;
end;

procedure TLoader.EndsWait;
begin
  TForm(Application.FindComponent('FWait')).Free;
end;

procedure TLoader.Execute;
begin
  inherited;
  Synchronize(ShowWait);
  // Do Some Job while not terminated
  Sleep(1000);
  // Free Wait Form
  // This part is not working
  Synchronize(EndsWait);
end;

procedure TLoader.ShowWait;
begin
  With TForm.Create(Application) do
    begin
      // Some code
      Name:= 'FWait';
      ShowModal;
    end;
end;

end.

除了 Synchronize(EndsWait); 没有关闭和 Release模式窗体之外,一切都如我所料。

如何在 TThread 运行时显示模式窗体并在 TThread 终止时释放它?


更新:

我尝试按照 Remy 的建议进行以下操作:

type
  TForm2 = class(TForm)
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TLoader = class(TThread)
    protected
      procedure DoTerminate; override;
      procedure DoCloseModal;
    public
      constructor Create;
      procedure Execute; override;
  end;
var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TLoader }

constructor TLoader.Create;
begin
  inherited Create;
  FreeOnTerminate:= True;
end;

procedure TLoader.DoCloseModal;
begin
  Form2.ModalResult:= mrOk;
end;

procedure TLoader.DoTerminate;
begin
  inherited DoTerminate;
  Synchronize(DoCloseModal);
end;

procedure TLoader.Execute;
begin
  inherited;
  Sleep(200);
end;

procedure TForm2.FormShow(Sender: TObject);
begin
  TLoader.Create;
end;

end.

主窗体按钮点击事件处理程序:

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TForm2.Create(nil) do
    try
      ShowModal;
    finally
      Free;
    end;
end;

最佳答案

你有两个选择:

  1. 不要一开始就使用模态形式。 TThread.Synchronize() 会阻塞您的线程,直到同步方法退出,但是 TForm.ShowModal() 会阻塞该方法,直到 Form 关闭。使用 TThread.Synchronize()(或者更好,TThread.Queue())到 Create()+Show()(不是 ShowModal())Wait Form,然后返回到线程并让它根据需要完成它的工作,然后是 Synchronize()/Queue( ) 再次(或者,使用线程的 OnTerminate 事件)到 Close()+Free() Wait Form 完成。

  2. 或者,如果您想使用模态等待表单,则根本不要让线程管理等待表单。让您的按钮 OnClick 处理程序 Create()+ShowModal()(不是 Show())等待表单,和 Free()ShowModal() 退出时。当等待表单显示和关闭时,分别让等待表单在内部创建和终止线程。如果线程在 Wait Form 关闭之前结束,线程的 OnTerminate 处理程序可以 Close() Form(它只是设置 Form 的 ModalResult)这样 ShowModal() 将在 OnClick 处理程序中退出。

关于multithreading - 如何从线程显示 "Please wait "模态表单并在工作完成后释放它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63001159/

相关文章:

c# - 使用 C# 在两个或多个进程之间共享 int 值?

c - 是否可以在线程中使用退出?

Delphi 通过引用返回值

delphi - 为什么 EOutOfResources 中会泄漏内存?

html - 打开模式并滚动到特定 DIV

Java:WAITING同步块(synchronized block),谁先走?

c++ - 从后台线程切换到主线程

objective-c - 用Delphi XE2制作的.dylib不能被Xcode应用程序使用

javascript - 关闭 jQuery 中的模式弹出窗口

javascript - 如何使用具有相同 ID 的多个按钮打开相同模式?