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

程序终止后的Delphi任务和线程,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; pr

我有一个疑问,我不能解决在线或在我的德尔福书籍。看看这个

案例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:\Users\EmmaVMWare\Desktop\ts.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(“Fire and forget”),因为一旦开始,我们就放手了,它会自行清理。如果我在程序终止之前关闭程序,它会被正确地终止吗

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

procedure TForm1.Button1Click(Sender: TObject);
var s: ITask;
begin

  s := TTask.Run(procedure
                 begin
                  Sleep(5000);
                  TFile.WriteAllText('C:\Users\EmmaVMWare\Desktop\aa.txt', 'test');
                 end);
end;
这是案例1中的代码,但由于我使用了一个任务,所以键入的代码更少。在这种情况下,情况就不同了

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


  • 任务。一旦启动,它将一直运行到结束,无论我是否在程序终止前关闭程序
  • t线程子类。一旦启动,它将一直运行到结束,但如果我在程序终止之前关闭程序,它将死亡(?)
如上所述,我想知道(在案例1中)是否可以在线程终止之前关闭程序。因为我以为我可以写下这样的话:

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

基本上,我不确定是必须在代码中调用
终止
,还是在程序死机时自动调用。从我的测试中看到,这只影响线程子体,而不影响任务。

这与文件无关。与Delphi运行时处理任务的方式相比,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;
在调试器中运行此应用程序。您将注意到,对于Button1,您的应用程序将立即退出。对于按钮2,您的程序似乎已消失(表单已关闭),但仍在运行!最后,五秒钟后,调试器将在
Winapi.Windows.DebugBreak()
上中断

奖金:
更改
TTask.Run(backgroundStuff)
to
TTask.Run(backgroundStuff,TThreadPool.Create())
并查看发生了什么。

您不能在将
FreeOnTerminate
设置为
True
的线程上调用
Terminate
。如果在线程执行时终止进程,它将被强制终止。然后呢?这取决于线程正在做什么。也许这不重要,也许会。使用关机事件而不是睡眠,所有线程都使用
WaitForSingleObject
并等待关机事件。如果等待超时,它们将继续执行其他操作,而不会终止。