0

这是一个秒表的示例代码,我已经使用 OmniThread 库作为单独的线程实现。

这是我的问题:我是否必须在表单关闭时终止并取消任务,还是在表单关闭时自动销毁?

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;
4

1 回答 1

1

“使用 OmniThreadLibrary 进行并行编程”一书的作者 Primož Gabrijelčič 写道:

“我们还应该通过在后台扫描程序处于活动状态时单击“X”按钮来处理用户关闭程序的可能性。我们必须捕获 OnFormCloseQuery 事件并告诉任务终止。

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

这本书在http://leanpub.com/omnithreadlibrary有售

于 2014-09-22T14:10:25.740 回答