Sam*_*ami 2 delphi multithreading 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.
Run Code Online (Sandbox Code Playgroud)
一切都按我的预期工作,除了Synchronize(EndsWait);没有关闭和释放模态表单。
如何在 aTThread运行时显示模态表单并在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.
Run Code Online (Sandbox Code Playgroud)
主窗体按钮单击事件处理程序:
procedure TForm1.Button1Click(Sender: TObject);
begin
with TForm2.Create(nil) do
try
ShowModal;
finally
Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
你有两个选择:
不要使用模态形式开始。TThread.Synchronize()在同步方法退出之前阻止您的线程,但TForm.ShowModal()在表单关闭之前阻止该方法。使用TThread.Synchronize()(或更好,TThread.Queue())Create()+ Show()(不是ShowModal())Wait Form,然后返回到线程并让它根据需要完成它的工作,然后Synchronize()/Queue()再次(或使用线程的OnTerminate事件)在完成后Close()+ Free()Wait Form。
或者,如果您想使用模态等待表单,则根本不要让线程管理等待表单。让您的按钮OnClick处理程序Create()+ ShowModal()(不是Show())等待表单,并Free()在ShowModal()退出时使用它。当等待表单显示和关闭时,让等待表单在内部创建和终止线程。如果线程在 Wait Form 关闭之前结束,则线程的OnTerminate处理程序可以处理Close()Form(它只是设置 Form 的ModalResult),以便ShowModal()将在OnClick处理程序中退出。