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

Emm*_*oli 1 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:\Users\EmmaVMWare\Desktop\ts.txt', 'test2');
end;
Run Code Online (Sandbox Code Playgroud)

这是VCL的实现:

procedure TForm1.Button1Click(Sender: TObject);
var s: Test;
begin
  s := Test.Create;
  s := nil;
end;
Run Code Online (Sandbox Code Playgroud)

我打开程序,单击按钮,等待5秒钟,我在桌面上看到该文件.但是如果我打开程序,我点击按钮,2秒钟后我关闭程序,我再也看不到文件了(5秒后).

我在delphi中阅读了nick hodges的更多编码,他说这种线程是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;
Run Code Online (Sandbox Code Playgroud)

这是案例1中的代码,但由于我使用了一个任务,因此键入较少.在这种情况下,事情是不同的!

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


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

如上所述,我想知道(在案例1中)是否可以在线程终止之前关闭程序.因为我以为我可以这样写:

procedure TForm1.FormDestroy(Sender: TObject);
begin
   if not(s.Terminated) then
     s.Terminate;
end;
Run Code Online (Sandbox Code Playgroud)

基本上我不确定是否必须调用Terminate代码或者在程序死亡时以某种方式自动调用它.从我在测试中看到的情况来看,这仅影响TThread后代和NOT Tasks.

Gün*_*ful 5

这与文件无关.与处理任务的方式相比,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;
Run Code Online (Sandbox Code Playgroud)

在调试器中运行此应用程序.您会注意到,对于Button1,您的应用程序将立即退出.对于Button2,您的程序似乎已消失(表单已关闭),但它仍在运行!最后,五秒钟后,您的调试器将会中断Winapi.Windows.DebugBreak().

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