程序终止后的Delphi任务和线程



我有一个疑问,我无法在线或在我的delphi书中解决。看看这个。

案例1。

type
Test = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
end;
constructor Test.Create;
begin
inherited Create(false);
FreeOnTerminate := true;
end;
procedure Test.Execute;
begin
inherited;
Sleep(5000);
TFile.WriteAllText('C:UsersEmmaVMWareDesktopts.txt', 'test2');
end;

这就是VCL的实现:

procedure TForm1.Button1Click(Sender: TObject);
var s: Test;
begin
s := Test.Create;
s := nil;
end;

我打开程序,点击按钮,等待5秒钟,我看到桌面上的文件。但如果我打开程序,我点击按钮,2秒钟后关闭程序,我就看不到文件了(5秒钟后(。

我读了nick hodges在delphi中的更多代码,他说这种线程是F&F("燃烧并忘记"(,因为一旦开始,我们就让它过去,它会自己清理。如果我在程序终止前关闭程序,它会被正确地杀死吗?

案例2.出于好奇,我也编写了以下代码:

procedure TForm1.Button1Click(Sender: TObject);
var s: ITask;
begin
s := TTask.Run(procedure
begin
Sleep(5000);
TFile.WriteAllText('C:UsersEmmaVMWareDesktopaa.txt', 'test');
end);
end;

这是案例1中的代码,但由于我使用了Task,所以键入较少。在这种情况下,情况就不一样了!

如果我运行程序,点击按钮并等待5秒钟,我可以看到文件。如果我运行程序,点击按钮,然后在2秒钟后(或者在任何情况下,在5秒钟之前(关闭程序,我仍然可以看到文本文件!


  • 任务。一旦启动,它将一直运行到结束,无论我是否在程序终止前关闭它
  • TThread子类。一旦启动,它会一直运行到最后,但如果我在程序终止前关闭它,它就会死(?(

如上所述,我想知道(在情况1中(在线程终止前关闭程序是否可以。因为我以为我可以写这个:

procedure TForm1.FormDestroy(Sender: TObject);
begin
if not(s.Terminated) then
s.Terminate;
end;

基本上,我不确定是必须在代码中调用Terminate,还是在程序失效时自动调用。从我的测试中看到,这只影响TThread的后代,而不影响任务。

这与文件无关。不幸的是,Delphi运行时处理线程的方式与处理任务的方式不同。

当你退出一个VCL应用程序时,后台线程会被终止。应用程序不会等待它们,它只是结束。如果你想等待它们,你必须自己编写代码。

然而,VCL应用程序将等待(如果需要的话,将永远等待(放入默认线程池(System.Threading.TThreadPool.Default(中的所有任务。

考虑以下示例VCL应用程序:带有两个按钮的空表单:

implementation uses System.Threading, Winapi.Windows;
procedure TForm1.Button1Click(Sender: TObject);
begin
TThread.CreateAnonymousThread(backgroundStuff).Start();
Application.Terminate();
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
TTask.Run(backgroundStuff);
Application.Terminate();
end;
procedure TForm1.backgroundStuff();
begin
Sleep(5000);
Winapi.Windows.DebugBreak();
end;

在调试器中运行此应用程序。您会注意到,对于按钮1,您的应用程序将立即退出。对于按钮2,您的程序似乎不见了(表单已关闭(,但它仍在运行!最后,五秒钟后,调试器将在Winapi.Windows.DebugBreak()上中断。

奖金:TTask.Run(backgroundStuff);更改为TTask.Run(backgroundStuff, TThreadPool.Create());,看看会发生什么。

最新更新