匿名线程不让应用程序关闭

时间:2017-02-20 02:06:24

标签: multithreading delphi-10.1-berlin

我有一个应用程序,用户可以以交互方式或从命令行运行。在第二种模式下,程序必须在完成时退出。

这是基本的最小代码。似乎从未设置application.terminated;

如何关闭此程序,无需用户交互。

unit Unit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls ;

type
  TForm4 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure DoSomeStuff;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject);
var
  anonThread : TThread;
begin
   anonThread := TThread.CreateAnonymousThread(procedure
   begin
     while not application.terminated do
     begin
       doSomeStuff;
    end;
   end);
   anonThread.Start;

end;

procedure TForm4.DoSomeStuff;
var
  i : integer;
begin
  for i := 0 to 10 do
    begin
      beep;
      sleep(100);
    end;
    application.Terminate;
end;


end.

1 个答案:

答案 0 :(得分:1)

Application.Terminated属性在主要UI线程中没有Application.Run()(或至少是调用Application.ProcessMessages()的手动循环)中的消息循环时不起作用。这是因为Application.Terminate()只是将WM_QUIT消息发布到调用线程的消息队列。在处理该消息之前,不会设置Application.Terminated。控制台应用通常不会调用Application.Run(),因此Application.Terminated无法在控制台应用上运行。

您应重新设计代码,以便在控制台模式下删除ApplicationTForm的依赖关系,例如:

program MyApp;

uses
  MyWorkUnit, Unit4;

begin
  if IsRunInCommandLineMode then
  begin
    DoSomeStuff;
  end else
  begin
    Application.Initialize;
    Application.CreateForm(TForm4, Form4)
    Application.Run;
  end;

end.

unit MyWorkUnit;

interface

procedure DoSomeStuff;

implementation

procedure DoSomeStuff;
var
  i : Integer;
begin
  for i := 0 to 10 do
  begin
    Beep;
    Sleep(100);
  end;
end;

end.

unit Unit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm4 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

uses
  MyWorkUnit;

procedure TForm4.Button1Click(Sender: TObject);
begin
   TThread.CreateAnonymousThread(
      procedure
      begin
        while not Application.Terminated do
          DoSomeStuff;
      end
    ).Start;    
end;

end.