使用 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;
我正在使用 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;