Meta Mussel
Meta Mussel

Reputation: 590

Anonymous Thread not letting application close

I have an application that the user can run either interactively or from command line. In the second mode, the program must exit upon completion.

Here is the basic minimal code. It seems that application.terminated is never set;

How do I get this program to close, w/o0 user interaction.

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.

Upvotes: 0

Views: 57

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596703

The Application.Terminated property doesn't work without the message loop in Application.Run() (or at least a manual loop that calls Application.ProcessMessages()) in the main UI thread. This is because Application.Terminate() simply posts a WM_QUIT message to the calling thread's message queue. Application.Terminated is not set until that message is processed. A console app typically does not call Application.Run(), so Application.Terminated does not work on a console app.

You should redesign your code to remove the dependency on Application and your TForm in console mode, eg:

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.

Upvotes: 1

Related Questions