Multithreading 后台线程何时阻止进程终止?

Multithreading 后台线程何时阻止进程终止?,multithreading,delphi,indy,terminate,Multithreading,Delphi,Indy,Terminate,我们的程序在程序开始时创建一个后台线程。后台线程使用Indy进行一些数据库完整性检查和Internet中的内容检查。10秒后,背景线程应该完成,因为FreeOnTerminate为true,所以它也会自行清理 我们注意到,在某些情况下,如果用户关闭程序的速度过快,则在后台线程完成之前,进程仍将处于活动状态 由于我们无法准确再现该问题,我创建了一个演示项目来尝试以下几点: type TBackgroundThread = class(TThread) protected proce

我们的程序在程序开始时创建一个后台线程。后台线程使用Indy进行一些数据库完整性检查和Internet中的内容检查。10秒后,背景线程应该完成,因为FreeOnTerminate为true,所以它也会自行清理

我们注意到,在某些情况下,如果用户关闭程序的速度过快,则在后台线程完成之前,进程仍将处于活动状态

由于我们无法准确再现该问题,我创建了一个演示项目来尝试以下几点:

type
  TBackgroundThread = class(TThread)
  protected
    procedure Execute; override;
  end;

{ TForm1 }

var
  bt: TBackgroundThread;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  // Create a background thread which runs X seconds and then terminates itself.
  bt := TBackgroundThread.Create(false);
  bt.FreeOnTerminate := true;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  // The user closes the app while the background thread is still active
  Sleep(2000);
  Close;
end;

{ TBackgroundThread }

procedure TBackgroundThread.Execute;
var
  i: integer;
  x: cardinal;
begin
  inherited;

  // Simulate some work that the background thread does
  x := MaxInt;
  for i := 0 to MaxInt do
  begin
    x := Random(x);
  end;
end;
结果让我有点惊讶:在我关闭MainForm之后,进程将立即终止,后台线程将被硬终止

现在我有几个问题:

  • 关闭MainForm(=退出主线程)后,我应该通过.terminate手动终止所有创建的线程,还是自动终止

  • 我的线程应该只检查自终止还是也检查应用程序终止

  • 为什么当我关闭应用程序时,上面显示的繁忙线程会立即被终止?我希望Project1.exe进程将一直运行,直到所有线程自己完成为止。(如上所述,我们看到了一个应用程序,其中主窗体是关闭的,但线程阻止关闭进程)

  • 那么,我们真正的应用程序的进程怎么可能不会因为正在运行的后台线程而终止呢?它可能与互联网有关,这可能会导致应用程序等待连接超时


  • 关闭主窗体并不等同于退出主线程。关闭表单后,代码将继续运行。特别是,这些单位已最后确定

    如果处理测试线程的
    OnTerminate
    事件,或者在
    Terminate
    方法中放置断点,您将看到程序退出时不会自动调用它。你得自己说了。但还要注意,线程不会因为调用了
    Terminate
    而停止运行。它继续运行,直到它自身停止或强制终止。调用
    WaitFor
    等待它终止

    不要费心检查
    应用程序。已终止
    ;线程的属性应该足够了

    当程序退出时,您的线程会被强制终止,因为最终您的程序会调用
    ExitProcess
    ,操作系统要做的一件事就是终止所有其他线程。它不会对它们调用
    Terminate
    ,因为操作系统不知道Delphi类和方法


    您必须进行更多的调试,以确定为什么您的程序不能为您的客户及时终止。你说你不能在家里重现这个问题,你已经编写了一个测试程序,也没有显示出这个问题。您必须找到一位客户,他将配合您进一步的调试工作。你真的知道是这根线支撑着一切吗,还是这只是目前的猜测?

    嗨。这是很多问题,但我们都经历过。我建议您阅读Joe Duffy的书“Windows上的并发编程”,学习基本概念(虽然不是那么基本),然后阅读Delphi文档。我认为Indy正在阻止您的线程立即完成。我猜你可以使用超时的阻塞套接字。但是@Lurd,阻塞套接字是否会阻止
    ExitProcess
    终止线程?“我对此表示怀疑。”RobKennedy说,“嗯,有一些版本的Indy带有可怕的析构函数,如果调用这些析构函数,就要等到所有的TidThread等实例都被终止。出于这些原因,我避免将Indy组件链接到表单和数据模块上,而只是在线程需要使用它们的时候创建它们。如果不可靠的析构函数从未被调用,它们将无法阻止访问ExitProcess(),从而阻止app close进程。一般来说,不要将线程子系统组件链接到窗体上。如果执行此操作,在app close上释放所属窗体将尝试释放组件,如果该组件是内部线程,则可能会在等待线程终止时卡住。在设置了
    FreeOnTerminate
    的线程上调用
    Waitfor
    是不安全的。看,谢谢。现在,很多事情变得更加清楚了。我重构了大部分代码,不再使用
    FreeOnTerminate
    。相反,我将所有创建的线程写入一个ObjectList,每个元素都将在程序终止时使用
    Terminate
    +
    WaitFor
    +
    Free
    进行处理(完成单元)。在每个线程中,我都会定期检查
    Self.Terminated