user1580348
user1580348

Reputation: 6053

Terminate and nil OmniThread task when form closes?

This is a sample code for a stopwatch I have implemented as a separate thread with the OmniThread library.

This is my question: Do I have to terminate and nil the task when the form closes or will it be destroyed automatically when the form closes?

uses
  System.SysUtils, System.Classes,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,

  OtlComm, OtlTask, OtlTaskControl, OtlEventMonitor;

type
  TForm1 = class(TForm)
    OTLMonitor: TOmniEventMonitor;
    btnStartClock: TButton;
    btnStopClock: TButton;
    procedure btnStartClockClick(Sender: TObject);
    procedure btnStopClockClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure OTLMonitorTaskMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
    procedure OTLMonitorTaskTerminated(const task: IOmniTaskControl);
  private
    { Private-Deklarationen }
    FClockTask: IOmniTaskControl;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ Place a TOmniEventMonitor component on the form,
  name it OTLMonitor,
  implement the OnTaskTerminated event-handler: OTLMonitorTaskTerminated
  and implement the OnTaskmessage event-handler: OTLMonitorTaskMessage }

var
  StopMessage: string;

procedure ShowElapsedSeconds(const ATask: IOmniTask);
var
  ElapsedSeconds: Integer;
begin
  ElapsedSeconds := 0;
  while not ATask.Terminated do
  begin
    // stop after 10 seconds:
    if ElapsedSeconds >= 10 then BREAK;

    Inc(ElapsedSeconds);
    ATask.Comm.Send(ElapsedSeconds);
    Sleep(1000);
  end;
end;

procedure TForm1.OTLMonitorTaskMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
begin
  // show elapsed seconds:
  Self.Caption := IntToStr(msg.MsgID);
end;

procedure TForm1.OTLMonitorTaskTerminated(const task: IOmniTaskControl);
begin
  FClockTask := nil;
  Self.Caption := StopMessage;
end;

procedure TForm1.btnStartClockClick(Sender: TObject);
begin
  if not Assigned(FClockTask) then // prevent multiple clock-tasks
  begin
    StopMessage := 'Automatically stopped after 10 seconds';
    FClockTask := CreateTask(ShowElapsedSeconds, 'ShowElapsedSeconds').MonitorWith(OTLMonitor).Run;
  end
  else
  begin
    MessageDlg('Clock is already running!', mtInformation, [mbOK], 0);
    { Nice: The clock continues to run even while this message dialog is displayed! }
  end;
end;

procedure TForm1.btnStopClockClick(Sender: TObject);
begin
  if Assigned(FClockTask) then
  begin
    StopMessage := 'Stopped by the user';
    FClockTask.Terminate;
    FClockTask := nil;
  end
  else
    MessageDlg('Clock is not running!', mtInformation, [mbOK], 0);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Assigned(FClockTask) then
  begin
    { Do I need to terminate and nil the clock-task here?
      Or will it be destroyed autmatically when the form closes? }
  end;
end;

Upvotes: 0

Views: 696

Answers (1)

user1580348
user1580348

Reputation: 6053

Primož Gabrijelčič, the author of "Parallel Programming with OmniThreadLibrary" writes:

"We should also handle the possibility of user closing the program by clicking the ‘X’ button while the background scanner is active. We must catch the OnFormCloseQuery event and tell the task to terminate.

procedure TfrmBackgroundFileSearchDemo.FormCloseQuery(Sender: TObject;
var CanClose: boolean);
begin
  if assigned(FScanTask) then
  begin
    FScanTask.Terminate;
    FScanTask := nil;
    CanClose := true;
  end;
end;"

This book is for sale at http://leanpub.com/omnithreadlibrary

Upvotes: 1

Related Questions