0

我正在使用 IOmniTaskControl/TOmniWorker 将代码执行集中到特定线程上。我将重复使用此 IOmniTaskControl 进行多次 Invoke 调用。如何检查调用期间可能发生的异常?这是问题/答案的后续问题:使用 IOmniTaskControl/TOmniWorker 时等待 Invoke 完成

我检查了 IOmniTaskControl 的 ExitCode 和 FatalException,但没有设置它们。似乎 IOmniTaskControl 将为每个 Invoke 调用自动创建一个新任务,如果发生异常,则会将异常置于该任务上。但是,在 Invoke 完成后,我没有提及该任务。我使用 TOmniWaitableValue 来标记调用何时完成,但不清楚我需要做什么才能使从 WaitFor(...) 返回时发生的任何异常对我可用。

这是我拥有的结构的一个片段:

interface

type
  TMyTaskProc = reference to procedure;

  TMyTask = class
  private
    FWorker:      IOmniWorker;
    FTaskControl: IOmniTaskControl;
    FWaitable:    IOmniWaitableValue;
  public
    constructor Create;
    destructor Destroy; override;

    procedure AwaitInvoke(Proc: TMyTaskProc); overload;
  end;

implementation

type
  TMyTaskWorker = class(TOmniWorker);

constructor TMyTask.Create;
begin
  inherited;

  FWorker := TMyTaskWorker.Create;
  FTaskControl := CreateTask(FWorker).Run;
  FWaitable := TOmniWaitableValue.Create;
end;

destructor TMyTask.Destroy;
begin
  FTaskControl.Terminate;
  FTaskControl := nil;

  FWaitable := nil;

  inherited;
end;

procedure TMyTask.AwaitInvoke(Proc: TMyTaskProc);
begin
  FWaitable.Reset;

  FTaskControl.Invoke(
    procedure
    begin
      try
        Proc();
      finally
        FWaitable.Signal;
      end;
    end
  );

  FWaitable.WaitFor(INFINITE);
end;

因此,在上述设置中,如何在 FWaitable.WaitFor(INFINITE) 之后检查 Proc() 调用期间可能发生的任何异常。我想在调用线程中再次提出它。

4

1 回答 1

1

您必须在调用 Proc 时捕获异常,然后以某种方式通知调用者该情况。例如:

FTaskControl.Invoke(
  procedure
  var
    return: TOmniValue;
  begin
    return := TOmniValue.Null;
    try
      try
        Proc();
      except
        return.AsException := AcquireExceptionObject;
      end;
    finally
      FWaitable.Signal(return);
    end;
  end
);

FWaitable.WaitFor(INFINITE);
if FWaitable.Value.IsException then begin
  Writeln('Caught exception ' + FWaitable.Value.AsException.ClassName);
  FWaitable.Value.AsException.Free;
end;
于 2016-03-28T17:18:23.813 回答