Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi einen laufende Ausführung stoppen (https://www.delphipraxis.net/97242-einen-laufende-ausfuehrung-stoppen.html)

DelphiManiac 7. Aug 2007 15:07


einen laufende Ausführung stoppen
 
Hallo,

ich habe eine Software für einen Prüfstand entwickelt.
was dort genau passiert habe ich schon hier beschrieben: Prüfsoftware...

Im großen und ganzen sieht das so aus,

ich habe eine abstrakte Klasse TTest, die die Methode Execute hat,
alle Nachfahren der Klasse TTest müssen diese Implementieren.

Beispiel:

Delphi-Quellcode:
  TTestRelais = class(TTest)
  private
  public
    constructor Create; override;
    function Execute:TTestResult; override;
  end;
Gut in der Execute Methode ist die Logik verborgen, die der Test implementiert,
z.B.: Relais 1 ansteuern, gucken ob es geschaltet hat usw...
Sie gibt ein Testresult zurück, (ob erfolgreich, wenn nein, warum nicht..)

Nun habe ich versuch möglichst objektorientiert ranzugehen und habe eine TTestControl Klasse erstellt,
die die Aufgabe hat Tests entgegenzunehmen und First In First Out auszuführen, d.h. die Execute Methode der
TTest-Klasse auszuführen.

Meine GUI erzeugt die Tests und fügt sie TTestControl zu.

Gesteuert werden sollen die Tests nur über TTestControl.

Ich möchte aber nun natürlich noch einen Testabbruch-Button haben, der mir die Testausführung abbricht.
Habe es bisher so gemacht, dass ich es TTestControl mitteile und TTestControl wenn es den nächsten Test ausführen will über
prüft, ob abgebrochen werden soll, und dann ggf. abbricht.

Nun kommt es aber vor, das z.B.: bei eine Kalibrierung in der TTest Execute Methode sehr lange brauch, bis sie fertig ist,
d.h. ich müsste den TTest direkt abbrechen können,

hoffe ihr versteht mein Problem, ich will es möglichst OOP-konform lösen


Danke euch
(Sorry für den langen Text, aber hoffe er hilft für das Verständnis)

Luckie 7. Aug 2007 15:12

Re: einen laufende Ausführung stoppen
 
Ich würde das in einen Thread auslagern, denn wenn die Execute-Methode so lange dauert dürfte dein Porgramm auch nicht mehr reagieren. Diesen Thread kannst du dann auch "von aussen" beenden. Wobei das natürlich nicht ganz ungefährlich ist, da du nicht weißt in welchen Zustand sich gerade die Daten in der Execute-Methode befinden. Aber du kannst in der Execute-Method eimmer mal wieder prüfen, ob sich der Thread beenden soll und dann vorher noch entsprechend im Thread aufräumen.

Klaus01 7. Aug 2007 15:15

Re: einen laufende Ausführung stoppen
 
Nun wenn Du nicht auf Thread umsteigen möchtest,
kannst Du nicht im Objekt TTest eine Variable (abbruch) einführen,
die den Wert false hat wenn die Execute Methode durchlaufen soll und auf den Wert true
gesetzt wird wenn die Execute Methode gestoppt werden soll.

In der Execute Methode/Schleife kannst Du dann diese Variable abfragen.

Grüße
Klaus

DelphiManiac 7. Aug 2007 16:06

Re: einen laufende Ausführung stoppen
 
@Klaus01:

Ja das Könnte ich machen, aber meine GUI kennt ja die TTests gar nicht,
und weiß auch gar nicht welche TTest aktiv ist, das weiß nur TTestcontrol,
das wiederum die Ausführung steuert.

Ich will auch gar nicht, dass die GUI die Logik besitzt um einen Test zu beenden, sie soll es nur der darüber liegenden
Logik (TTestControl) übergeben, und die soll den TTest beenden, aber ich weiß nicht wie?

Klaus01 7. Aug 2007 16:14

Re: einen laufende Ausführung stoppen
 
Nun, wenn Dein Objekt TTestControl weiß welcher Test gerade aktiv ist,
kannst Du dann nicht z.b. dem Objekt TTestControl noch die Methode
setStopFlagAtActiveTest einbauen.
Diese Methode setzt dann über eine setMethode des TTest Objekts das entsprechende Flag.

Die TestControl.setStopFlagAtActiveTest kann ja durch den AbbruchButton aktiviert werden.

Oder ist das zu einfach gedacht.

Grüße
Klaus

Reinhard Kern 7. Aug 2007 18:53

Re: einen laufende Ausführung stoppen
 
Zitat:

Zitat von DelphiManiac
@Klaus01:

Ja das Könnte ich machen, aber meine GUI kennt ja die TTests gar nicht,
und weiß auch gar nicht welche TTest aktiv ist, das weiß nur TTestcontrol,
das wiederum die Ausführung steuert.

Ich will auch gar nicht, dass die GUI die Logik besitzt um einen Test zu beenden, sie soll es nur der darüber liegenden
Logik (TTestControl) übergeben, und die soll den TTest beenden, aber ich weiß nicht wie?

Deine GUI kann doch den TTests eine neuen Auftrag übergeben, dann wird sie TTests ja wohl auch anweisen können, eine Variable ContinueTest auf false zu setzen - und dann stoppt die Ausführung eben bei der nächsten Abfrage dieser Variable. Egal ob extra Thread oder nicht.

Falls das zu einfach ist, kann man natürlich auch noch einige überflüssige Klassen darum herum bauen. Der einfachste Fall allerdings wäre eine für die ganze Anwendung globale Variable ContinueTest, auch wenn hier einige religiöse Eiferer gleich wieder nach Kreuzigung rufen werden. Dem Programm allerdings ist die angeblich reine Lehre herzlich egal, das funktioniert so einwandfrei.

Gruss Reinhard

DelphiManiac 7. Aug 2007 20:55

Re: einen laufende Ausführung stoppen
 
@Klaus01:

also wenn ich meiner Klasse TTestControll noch eine Methode zum setzen eine Abbruchanweisung gebe,
dann kann ich ja dann die Abbruch Methode des aktiven TTestobjekts aufrufen,
ich müsste dann meine abstrakte TTestklasse noche erweitern:

Delphi-Quellcode:
TTestRelais = class(TTest)
  private
  public
    constructor Create; override;
    function Execute:TTestResult; override;
    function Abbruch:Boolean; override // überschreiben der abstrakten Methode aus Klass TTest
  end;
Gut und in TTestControl rufe ich dann die Methode auf...

...
Delphi-Quellcode:
procedure TTestControl.BrecheTestAb;
begin
  TTest(aktuellerTest).Abbruch;
end;
Ich probiere das morgen aus, und gebe Rückmeldung...

Gruß
und Danke

DelphiManiac 8. Aug 2007 15:25

Re: einen laufende Ausführung stoppen
 
@Reinhard Kern



Zitat:

Deine GUI kann doch den TTests eine neuen Auftrag übergeben, dann wird sie TTests ja wohl auch anweisen können, eine Variable ContinueTest auf false zu setzen - und dann stoppt die Ausführung eben bei der nächsten Abfrage dieser Variable. Egal ob extra Thread oder nicht.
Ja da hast du Recht, meine GUI übergibt (je nachdem welches Häckchen gesetzt ist) die TTests an die TestControll Klasse,
aber es soll sie ja gar nicht interessieren, ob und welcher Test aktiv ist, das soll und weiß nur TTestControll,
meine Controller Klasse abstrahiert dieses Wissen.

Ich sage ja nicht, dass es mit deinem Vorschlag nicht geht, aber ich habe in letzer Zeit gemerkt, wenn man nur halbherzig OOP
einsetzt, dann fällt einem das irgendwann auf die Füße, deswegen, wollte ich den OOP-Weg an der Stelle gehen,

"richtig" oder "falsch" gibt es ja sowieso nicht.

Ich habe es aber jetzt so wie Klaus01 es vorgeschlagen hat gemacht,
d.h.

Die GUI, die ja den Controller (vom Typ TControlTest) kennt weißt diesen an, den aktuellen Test,
den ja die Controller Klass kennt zu beenden,(es wird dann eine Setter Methode des Tests aufgerufen,
und intern dann eine Variable

Delphi-Quellcode:
FshouldStopp:=true;
gesetzt, diese überprüfe ich dann auf true (vorallendingen in meinen Schleifen...) und breche dann ab


@Luckie:
Das mit einem Thread hatte ich mir auch schon überlegt, aber dann wieder verworfen, da ich über Prozedurzeigern sehr oft Methoden der GUI aufrufe, und ich dann wieder hätte synchronisieren müssen...

Danke allen, die sich hier beteiligt haben :mrgreen:

Gruß
DelphiManiac


// Formatierung geändert


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:33 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz