使用 IOmniTaskControl/TOmniWorker 时如何检查异常?

How can I check exceptions when using IOmniTaskControl/TOmniWorker?

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

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

这是我的结构片段:

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() 调用期间可能发生的任何异常。我想在调用线程的那个点再次提出它。

您必须在调用 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;