Seite 1 von 1

Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 11:24
von Wolfgang_B
Hallo,
ich melde mich wieder mal mit meinem alten Problem der Laufschrift ("Bitte warten ...."), die in einem eigenen Thread läuft. Das Thema hatten wir schon in dem Thread -> "Static Objekt in Funktion wird nicht gelöscht" ...

Das hat auch alles schön funktioniert, dummerweise habe ich es nur immer mit einer Auswertung probiert, die auch ein Ergebnis geliefert hat. Jetzt ist mir aufgefallen, daß die Laufschrift nur beim ersten Mal erscheint, d.h. ich starte eine Auswertung -> Laufschrift läuft. Beim nächsten Aufruf (vorher Funktion beendet) erscheint die Laufschrift nicht mehr. Warum? Beim Neuaufrufen der Funktion müßte doch der Thread wieder neu gestartet werden?

Code: Alles auswählen

FUNCTION LISTE_DRUCKEN()

  oThread2:Start( "MELDUNG", drawingArea, oThread2:threadID )

DO CASE

Code
.
.
Code

ENDCASE

MELDUNGSTOP(.T.)	

RETURN(NIL)

FUNCTION MELDUNG( drawingArea, id)																																// <-- LISTE_DRUCKEN() - (149)
  LOCAL xpos := 600
  
  //MsgBox("Meldung -> "+ALLTRIM(STR(id))  )
  // id -> nur zur Kontrolle des Threads
  // 
  oXbp := XbpStatic():new( drawingArea, , {xpos,10}, {500,25},{{XBP_PP_FGCLR, 13}, { XBP_PP_COMPOUNDNAME, "14.ARIAL Fett" } } )
  oXbp:create()
   
  DO WHILE !MeldungStop()
    IF xpos <=10
      xpos := 600
    ENDIF  
    oXbp:SetPos({xpos,10})
    oXbp:setCaption("Bitte einen Augenblick Geduld, Daten werden geladen ...")
    xpos-=3
    inkey(.2)
  ENDDO  
  
  oXbp:destroy()

RETURN( NIL )
// ENDFUNCTION MELDUNG()

FUNCTION MeldungStop(lSet)																																			// <-- LISTE_DRUCKEN() 3313 (.T. wenn Stopp)
STATIC lStop := .F.
IF PCount()>0
  lStop := lSet
ENDIF
RETURN lStop
// ENDFUNCTION MeldungStop(lSet)

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 12:38
von georg
Hallo, Wolfgang -


das ist immer wieder das alte Problem mit Code-Ausschnitten, es fehlt hin und wieder was wichtiges ...

Wie initialisierst Du oThread2? Ist es eine Static-Variable, die Du nur einmal initialisierst, oder eine Local-Variable, die bei jedem Aufruf neu erstellt wird? Wie sieht die Definition weiterer Parameter des Threads aus, ich denke da an atEnd() und dergleichen?

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 12:46
von Wolfgang_B
Hallo Georg,

ich verwende eine Local variable für den Thread:

Code: Alles auswählen

FUNCTION LISTE_DRUCKEN()

LOCAL oThread2  := Thread():new()

oThread2:Start( "MELDUNG", drawingArea, oThread2:threadID )

DO CASE

ENDCASE
MELDUNGSTOP(.T.)
ansonsten definiere ich nichts weiter. Beendet wird der Thread nach ENDCASE mit MELDUNGSTOP(.T.).

Funktioniert ja auch. Allerdings trotz neuem Aufruf der Funktion LISTE_DRUCKEN() und neuer Variable LOCAL oThread2 := Thread():new() nur einmal ...

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 14:02
von georg
Hallo, Wolfgang -


wenn mir das passieren würde, dann würde ich in der Funktion Meldung einen Breakpoint definieren und sehen, was beim zweiten Durchlauf passiert.

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 14:18
von Wolfgang_B
so der dezente Hinweis, daß ich mich doch mal mit der Workbench beschäftigen sollte ... :?

Danke und Gruß
Wolfgang

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 15:59
von Tom
MeldungStop(.F.) zwischendrin mal? :wink:

Edit: Das (MeldungStop()) ist Get-Set-Funktion. Du setzt sie auf .T., damit der Thread zum ersten Mal endet. Du musst sie wieder mit .F. besetzen, damit er beim zweiten Mal starten kann - ansonsten beendet er sich gleich wieder.

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 17:23
von Wolfgang_B
Hallo Tom,
das wars!!! Danke! Wie kommt man denn da drauf?

Was ich nicht verstehe, daß der Wert, der nirgends in einer Variable definiert ist und nur für die Übergabe gesetzt wird, nach Verlassen der Hauptfunktion (LISTE_DRUCKEN()) noch gültig ist ..

Gruß Wolfgang

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 17:31
von Tom
Hallo, Wolfgang.

Freut mich!
Wie kommt man denn da drauf?
Weil mir das auch schon passiert ist. Diese Get-Set-Funktion arbeitet letztlich wie eine globale Variable (PUBLIC). Wenn Du sie ohne Parameter aufrufst, sagt sie Dir, auf welchem Wert sie gerade steht. Wenn Du sie mit einem Wert aufrufst, setzt sie diesen Wert und gibt ihn zurück. Mit "MeldungStop(.T.)" willst Du allen (!) Threads, die darauf reagieren, sagen, dass sie aufhören können. Wenn's wieder von vorne losgehen soll, musst Du den Schalter natürlich erst einmal wieder auf GO! legen. :wink:

Re: Habe wieder mal Thread-Problem

Verfasst: So, 11. Mär 2018 17:43
von Wolfgang_B
nachvollziehbar. Da muß man aber erstmal draufkommen. Ich hätte nicht einmal gewußt, wo ich suchen soll ...

Noch einen schönen Sonntag

Gruß Wolfgang

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 18:17
von AUGE_OHR
Anmerkung :

mit MELDUNGSTOP(.T.) hältst du den Thread zwar an aber das Thread Object ist immer noch aktive :!:

also immer schön "aufräumen" wenn man mit Threads arbeitet denn das Thread Object wird nicht automatisch o:destroy()

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 18:21
von Wolfgang_B
Hallo Jimmy,
wenn ich das richtig interpretiere, heißt das bei meinem Code, daß bei jedem Aufruf der Funktion eine Thread-Leiche übrigbleibt?

Gruß Wolfgang

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 18:31
von Tom
Quack.

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 18:32
von Wolfgang_B
Zusatzfrage: Wie kann ich feststellen, daß noch ein spezielles TreadObjekt aktiv ist?

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 19:31
von AUGE_OHR
Wolfgang_B hat geschrieben: So, 11. Mär 2018 18:21 heißt das bei meinem Code, daß bei jedem Aufruf der Funktion eine Thread-Leiche übrigbleibt?
sorry ich hatte nur "wiederholt" im Kopf aber das machst du ja nicht so wie ich es meinte.

ein

Code: Alles auswählen

oThread:Destroy()
gibt es ja nicht

ich meinte wenn man

Code: Alles auswählen

o:SetInterval(nSec) 
benutzt muss man auch

Code: Alles auswählen

o:SetIntervall( NIL )
setzen um den Thread zu stoppen

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 19:33
von AUGE_OHR
Wolfgang_B hat geschrieben: So, 11. Mär 2018 18:32 Zusatzfrage: Wie kann ich feststellen, daß noch ein spezielles TreadObjekt aktiv ist?
siehe dir mal das an

Code: Alles auswählen

   aInfo := ThreadInfo( THREADINFO_TID      + ;
                        THREADINFO_SYSTHND  + ;
                        THREADINFO_FUNCINFO + ;
                        THREADINFO_TOBJ       )
   msgbox( VAR2CHAR(aInfo) )

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 21:53
von Tom
Wenn die Routine im Thread endet, endet auch der Thread. Da muss nichts zerstört oder genilt werden. Ein einfaches RETURN genügt.

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: So, 11. Mär 2018 23:18
von AUGE_OHR
JA, sorry ...

ich hatte wie schon gesagt bei "wiederholt" an o:SetInterval() gedacht was Wolfgang aber gar nicht verwendet #-o

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: Mo, 12. Mär 2018 9:35
von Tom
SetInterval(x) hat eine ähnliche Funktionalität wie SetTimerEvent(). Es bewirkt, dass der Code(block), der via Start() einem Thread zugewiesen wurde, alle x Hundertstelsekunden ausgeführt wird. Wenn man also möchte, dass eine Synchronisationsfunktion einmal pro Sekunde aufgerufen (!) wird, verwendet man so etwas. Das ist aber kein Timer, der irgendwie innerhalb der aufgerufenen Funktion verwendet wird oder werden kann. Sie wird mit jedem Feuern des Timers erneut aufgerufen.

Und ich empfehle die Visite der Doku, um sich dort bei Gelegenheit mal auflisten zu lassen, welche Klassen "Destroy()" kennen. Das sind nämlich ausschließlich Klassen, über die XbParts im weitesten Sinne (und Fenster allgemein und Automation Objects als Sonderfälle) verwaltet werden. Nur da hat Destroy() überhaupt Sinn, weil nur da gebraucht wird, was Destroy() macht, nämlich Systemressourcen freigeben, die für ein Objekt angefordert wurden. Es wird aber nicht gelöscht. Man kann es durch ein erneutes Create() wiederbeleben. Für die Speichervariable, in der es verwaltet wird, ist all das komplett irrelevant.

Objekte sind letztlich Variablentypen. Wenn man sie mit NIL belegt oder schlicht eine Routine beendet, in der sie LOCAL definiert waren, sind sie weg. Das kann man auch mit einem Objekt machen, das zufällig gerade einen Thread verwaltet. Aber nötig ist das meistens nicht. Eigentlich nie. Code in einem Thread endet, wie Code generell endet. Es sei denn, man arbeitet mit bestimmten Eigenschaften, die Threads haben können (siehe oben).

Re: Habe wieder mal Thread-Problem [erledigt]

Verfasst: Mo, 12. Mär 2018 19:18
von AUGE_OHR
@Tom : JA du hast ja Recht ... ich hab wie schon gesagt an was anderes gedacht.

angenommen ich will eine Aktion starten wenn die App nicht innerhalb der Zeit reagiert.
ich starte also einen Thread vor der beabsichtigten Aktion.

wenn die Aktion nicht innerhalb einer definierten Zeit antwortet soll der Thread active werden und ihn raus werfen.
da die Aktion mehrfach passiert möchte ich die Variabel wiederverwenden

Code: Alles auswählen

STATIC oThread4 := NIL                                      // re-use it

   ERRORLEVEL( 5 )
   IF oThread4 = NIL
      oThread4 := Thread() :new()                           // start timeout thread
   ENDIF
   oThread4:setStartTime( SECONDS() + 5 + 5 + 5 )
   oThread4:start( "NEWF2", @lExit )

   BEGIN SEQUENCE
      // hier kann sich die App aufhängen
   RECOVER
      // hier recover
   END   
die Frage ist also wie beende ich den Thread
1.) wenn alles OK ist
2.) nach Abbruch