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

时间:2018-07-17 13:38:58

标签: 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;

这是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:\Users\EmmaVMWare\Desktop\aa.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后代,而不影响Tasks。

1 个答案:

答案 0 :(得分: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;

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

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