Reputation: 148
I'm using an IOmniTaskControl/TOmniWorker to funnel code execution onto a specific thread. I'll reuse this IOmniTaskControl repeatedly for multiple Invoke calls. How do I check for exceptions that may have occurred during the Invoke? This is a follow on question to the question/answer: Waiting for Invoke to finish when using IOmniTaskControl/TOmniWorker.
I've checked the ExitCode and FatalException of the IOmniTaskControl but they are not set. It seems that the IOmniTaskControl will create a new task automatically for each Invoke call, and the exception gets placed onto that task, if it occurs. However, I have no reference to that task following the completion of the Invoke. I'm using a TOmniWaitableValue to flag when the invoke completes, but not clear on what I will need to do to make any exception that occurred available to me on return from the WaitFor(...).
Here is a snippet of the structure I have:
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;
So in the above setup, how can I check after FWaitable.WaitFor(INFINITE) for any exception that might have occurred during the Proc() call. I'd like to just raise it again at that point in the calling thread.
Upvotes: 1
Views: 196
Reputation: 26830
You have to catch the exception at the point when you call Proc and then somehow notify the caller of the situation. For example:
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;
Upvotes: 2