我一直在努力制作一个模态表单来通知用户等待作业结束。 这是我正在尝试做的一个简单示例:
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;
最佳答案
你有两个选择:
不要一开始就使用模态形式。
TThread.Synchronize()
会阻塞您的线程,直到同步方法退出,但是TForm.ShowModal()
会阻塞该方法,直到 Form 关闭。使用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
处理程序中退出。
关于multithreading - 如何从线程显示 "Please wait "模态表单并在工作完成后释放它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63001159/