2016-03-28 18 views
0

Ich verwende einen IOmniTaskControl/TOmniWorker, um die Codeausführung auf einen bestimmten Thread zu trichterieren. Ich werde dieses IOmniTaskControl wiederholt für mehrere Invoke-Aufrufe verwenden. Wie kann ich nach Ausnahmen suchen, die während des Invoke aufgetreten sind? Dies ist eine Frage zur Frage/Antwort: Waiting for Invoke to finish when using IOmniTaskControl/TOmniWorker.Wie kann ich Ausnahmen überprüfen, wenn ich IOmniTaskControl/TommiWorker verwende?

Ich habe die ExitCode und FatalException der IOmniTaskControl überprüft, aber sie sind nicht festgelegt. Es scheint, dass das IOmniTaskControl automatisch eine neue Aufgabe für jeden Invoke-Aufruf erstellt, und die Ausnahme wird auf diese Aufgabe platziert, wenn sie auftritt. Ich habe jedoch nach Abschluss des Aufrufs keinen Hinweis auf diese Aufgabe. Ich verwende einen TOmniWaitableValue, um zu kennzeichnen, wann der Aufruf abgeschlossen ist, aber nicht klar, was ich tun muss, um eine eventuell aufgetretene Ausnahme bei der Rückkehr von WaitFor (...) verfügbar zu machen.

Hier ist ein Ausschnitt aus der Struktur I haben:

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 der obigen Setup, wie kann ich überprüfen, nachdem FWaitable.WaitFor (unendlich) für jede Ausnahme, die während des Proc aufgetreten sind() Anruf. Ich möchte es an dieser Stelle im Calling-Thread noch einmal anheben.

+0

Konnten Sie kein vollständiges Programm erstellen, das eine Ausnahme ausgelöst hat? Auf diese Weise würden wir nicht raten müssen. Es fühlt sich an, als ob wir das hier zu fast jeder Frage stellen müssen. –

+0

Nicht sicher, ob es klar war oder nicht, aber ich sprach nicht von einer bestimmten Ausnahme. Ich versuche nur den Code einzurichten, um mögliche Ausnahmen im Aufruf von Proc() zu behandeln. Es erschien nicht notwendig, ein vollständiges Arbeitsprogramm bereitzustellen, das eine falsche Ausnahme im Aufruf von Proc() enthält. Tatsächlich hat Gabr mir die Antwort gegeben, die ich brauchte. –

+0

Nun schreiben Sie weiter eine halbe Frage. Wenn du hast, was du brauchst, was ist sonst noch wichtig? –

Antwort

1

Sie müssen die Ausnahme an dem Punkt abfangen, an dem Sie Proc anrufen und dann den Anrufer irgendwie benachrichtigen. Zum Beispiel:

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; 
+2

Das ist nicht gut. Das Ausnahmeobjekt wird beim Abschluss des Ausnahmehandlers zerstört. Sie benötigen 'AcquireExceptObject'. –

+1

@DavidHeffernan, natürlich. Ich habe vergessen, wie meine eigene Software funktioniert :((War unter dem Eindruck, dass TOmniValue.AsException das handhabt.) Fixed. – gabr

+0

Danke, die Ausnahme selbst zu fangen und Trunning war der Ansatz, den ich nehmen würde, wenn es etwas nicht gäbe, das mir fehlte Ich würde AqcuireExceptObject verwenden. –