【问题标题】:Accessing parameter in OmniThread parallel task aborts the task访问 OmniThread 并行任务中的参数会中止任务
【发布时间】:2014-09-22 20:20:57
【问题描述】:

在使用OmniThread库创建并行任务的程序中,当我尝试访问并行任务中的参数时,参数访问之后的代码没有执行,显然任务中止:

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

  OtlComm, OtlTask, OtlTaskControl, OtlEventMonitor;

type
  TForm1 = class(TForm)
    btnStartOTLTask: TButton;
    OTLMonitor: TOmniEventMonitor;
    procedure btnStartOTLTaskClick(Sender: TObject);
    procedure OTLMonitorTaskMessage(const task: IOmniTaskControl; const msg:
        TOmniMessage);
  private
    { Private-Deklarationen }
    FTestTask: IOmniTaskControl;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

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

procedure TestParameters(const ATask: IOmniTask);
var
  test: Integer;
begin
  ATask.Comm.Send(16); // does execute
  test := ATask.Param['From']; // ?? <<<===========================
  ATask.Comm.Send(17); // does NOT execute!
end;

procedure TForm1.btnStartOTLTaskClick(Sender: TObject);
begin
  if not Assigned(FTestTask) then // prevent multiple tasks
    FTestTask := CreateTask(TestParameters, 'TestParameters')
                   .MonitorWith(OTLMonitor)
                   .SetParameters(['From', 0, 'To', 99])
                   .Run
  else
    MessageDlg('Task is already running!', mtInformation, [mbOK], 0);
end;

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

那么访问参数'From'有什么问题呢?

【问题讨论】:

  • 不只是在 OnTaskMessage 事件处理程序中设置标题,而是将消息放入备忘录或类似文件中以进行调试。调试时,在 TestParameters 中放置一个断点并单步执行所有行。在没有调用 FTestTask.Terminate 和 FTestTask := nil 的情况下测试 Assigned(FTestTask) 似乎很奇怪。
  • @LURD 我已经按照你说的做了,并逐步完成了TestParameters:在参数访问行中,我遇到了一个异常TOmniValueContainer.Getltem: Parameter From does not exist。所以很明显SetParameters 有问题,顺便说一句,它完全遵循 OmniThread 文档中的解释。
  • 它似乎只能以这种方式工作:test := ATask.Param.ByName('From'); AND 而不是SetParameters 与使用.SetParameter('From', 1).SetParameter('To', 99) 等的多次调用的开放数组。
  • 这是当前 SetParameter 实现中的一个错误。当我向 TOmniValue 添加数组支持时,底层存储发生了变化,并且未修改 SetParameters 以反映该变化。我会尽快解决这个问题。
  • @gabr 谢谢。你能告诉我如何在 SetParameter 中传递(然后访问)一个 TRect 吗?不支持.SetParameter('FormRect', Self.ClientRect)

标签: delphi parallel-processing delphi-xe2 omnithreadlibrary


【解决方案1】:

我找到了解决方法:

procedure TestParameters(const ATask: IOmniTask);
begin
  // this does work:
  ATask.Comm.Send(ATask.Param.ByName('From'));
  ATask.Comm.Send(ATask.Param.ByName('To'));

  // ALSO this does work:
  ATask.Comm.Send(ATask.Param['From']);
  ATask.Comm.Send(ATask.Param['To']);
end;

procedure TForm1.btnStartOTLTaskClick(Sender: TObject);
begin
  if not Assigned(FTestTask) then // prevent multiple tasks
    FTestTask := CreateTask(TestParameters, 'TestParameters')
                   .MonitorWith(OTLMonitor)
                   // SetParameters does not work:
                   //.SetParameters(['From', 1, 'To', 99])
                   // this does work:
                   .SetParameter('From', 1)
                   .SetParameter('To', 99)
                   .Run
  else
    MessageDlg('Task is already running!', mtInformation, [mbOK], 0);
end;

procedure TForm1.OTLMonitorTaskMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
begin
  Memo1.Lines.Add(IntToStr(msg.MsgID));
end;

procedure TForm1.OTLMonitorTaskTerminated(const task: IOmniTaskControl);
begin
  FTestTask := nil;
  Memo1.Lines.Add('Task terminated');
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 2015-08-23
    相关资源
    最近更新 更多