【问题标题】:Terminate and nil OmniThread task when form closes?表单关闭时终止并取消 OmniThread 任务?
【发布时间】:2014-09-22 11:52:15
【问题描述】:

这是我使用 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;

【问题讨论】:

  • OTLMonitorTaskTerminated 从未被引用。 FClockTask 在其拥有的对象被销毁时离开范围。就像任何其他变量一样。
  • @DavidHeffernan OTLMonitorTaskTerminated 是放置在表单上的OTLMonitor 组件的事件处理程序。它在任务终止时触发(10 秒后自动或由用户)。我觉得这里没有错。 “从未引用”是什么意思?
  • 好吧,我看不到 .dfm 文件。因此,从我在这里看到的情况来看,该方法从未被引用过。
  • @DavidHeffernan 我已经补充了实现 OTLMonitorTaskTerminated 事件处理程序的指令。对于第二点:所以我不必明确终止 FormClose 上的任务?谢谢!
  • 嗯,取决于FormClose。它是否破坏表单对象。你在使用什么关闭动作?

标签: delphi delphi-xe2 omnithreadlibrary


【解决方案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出售

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多