Alaska-Sample myThread

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Alaska-Sample myThread

Beitrag von Jan »

Hallo,

zu dem Beispiel in der Onlinehilfe habe ich eine Frage: Es geht dabei ja darum, einen Thread von außen zu beenden. Ich hab damit mal ein wenig rumgespielt, stolpere aber über ein Phänomen.

Was ich dabei gemacht habe ist: Die Threadvariable habe ich PUBLIC gemacht. Wenn ein Thread darauf erzeugt werden soll schaue ich vorher nach, ob die noch NIL ist. Wenn nicht rufe ich
beende und NILle ich den. Der neue Thread wird dann auch sauber auf die PUBLIC erstellt.

Wenn ich aber mir in der Workbench das Threads-Fenster anschaue, dann gibt es den Thread dort mehrfach. Halt so oft wie ich den aufgerufen hatte. Alle stehen in der Eventschleife.

Hab ich da einen Gedankenfehler? Oder ist das Sample von Alaska nicht ganz korrekt? Oder spinnt die Workbench?

Abgekürzt sieht das Ganze dann so aus:

Code: Alles auswählen

FUNCTION main

LOCAL i := 0
PUBLIC oThread := NIL

FOR i := 1 TO 10
    test()
    InKey(5)
NEXT

[Eventschleife]

RETURN NIL

FUNCTION test

IF MEMVAR->oThread <> NIL
   MEMVAR->oThread:terminate()
   MEMVAR->oThread := NIL
ENDIF

MEMVAR->oThread := myThread():new()
MEMVAR->oThread:start("testfunktion")

RETURN NIL

FUNCTION testfunktion

[Eventschleife]

RETURN NIL
Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Hallo Jan
Hab ich da einen Gedankenfehler?
Ja. Einen grossen!

Wenn du terminate() sendest ist das die Mitteilung an den Thread sich zu beenden. Du darfst die Variable nicht gleich auf NIL setzten weil der Thread noch läuft und du an der Stelle nicht mal weisst wie lange er noch läuft. Dies muss der Thread tun wenn er sich beendet.

Das Konzept mit der Variable bereitet dir vermutlich später auch noch viele viele weitere Probleme. Bei der Arbeit mit Threads würde ich dir ein Array empfehlen in welches du mit einer Klasse mit einer SYNCH Methode die Thread Infos usw. einträgst. Und auch ein Threadrecycling ist eigentlich ein muss.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Carlo,

das NILlen hatte ich erst später eingebaut, weil der Thread einfach nicht beendet wurde. Hat aber insgesamt nichts geändert am Verhalten.

Jetzt mal vollkommen abseits irgend welcher anderer Vorgehensweisen: Was ist in meinem Sample der Fehler? Der macht doch bei :terminate ein :quit(), also sollte der Thread beendet sein? Ich bin halt kein Klassenmensch, irgendwas übersehe oder mißverstehe ich da garantiert.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Hallo Jan

bei :terminate() wird im angesprochenen Thread das ausgeführt was du programmiert hast.
:quit() beendet die Codeausführung IM ausführenden Thread das Threadobjekt bleibt jedoch bestehen.
Es könnte mit :start() erneut gestartet werden.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Hallo Carlo,

ah! OK, das erklärt einiges. Ich war davon ausgegangen, das ein :quit() den Thread komplett beendet. Dann werd ich das mal so testen das ich den Thread beim erneuten Durchlauf nicht neu erstelle, sondern nur neu starte.

BTW: Wie beende ich denn dann einenThread komplett?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Hmmm. Das wars irgend wie nicht. Ich hab das jetzt mal so umgebaut:

Code: Alles auswählen

FUNCTION main

LOCAL i := 0
PUBLIC oThread := NIL

FOR i := 1 TO 10
    test()
    InKey(5)
NEXT

[Eventschleife]

RETURN NIL

FUNCTION test

IF MEMVAR->oThread <> NIL
   MEMVAR->oThread:terminate()

 ELSE
   MEMVAR->oThread := myThread():new()
ENDIF

MEMVAR->oThread:start("testfunktion")

RETURN NIL

FUNCTION testfunktion

[Eventschleife]

RETURN NIL
Der läuft zwar in Folge-Durchläufen auf :start(), führt den aber nicht aus.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Hallo Jan

da fehlt aber irgendwie die :Terminate() Methode ....
Valar Morghulis

Gruss Carlo
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Versuch mal das:

Code: Alles auswählen

********************************************
FUNCTION main

LOCAL i := 0
PUBLIC oThread := NIL

FOR i := 1 TO 1000
    test()
    DispOutAt( 1, 0, i )
    InKey(5) 
NEXT

RETURN NIL

FUNCTION test

IF MEMVAR->oThread <> NIL
   MEMVAR->oThread:terminate()

   do while MEMVAR->oThread:active 
    sleep(1)
   enddo


 ELSE
   MEMVAR->oThread := myThread():new()
ENDIF



MEMVAR->oThread:workCounter := 0
MEMVAR->oThread:start()

RETURN NIL





CLASS MyThread FROM Thread
      PROTECTED:
         VAR terminated
      EXPORTED:
         VAR workCounter

         INLINE METHOD init
            
            ::Thread:init()
            ::terminated  := .F.
            ::workCounter := 0
         RETURN self

         INLINE METHOD terminate
         RETURN ( ::terminated := .T. )

         METHOD execute
   ENDCLASS

   ** This method is executed in the thread
   METHOD MyThread:execute
      

      DO WHILE ::workCounter < 10000000
         // program code for thread
         DispOutAt( 0, 0, ::workCounter++ )

         IF ::terminated
            ::terminated := .F.
            
            ::quit()
         ENDIF

        
      ENDDO
          
           ::quit()

   RETURN self





Zuletzt geändert von ramses am Sa, 16. Mai 2020 21:35, insgesamt 4-mal geändert.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Leider keine Änderung.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Hallo Jan

beim mir läufts. Versuche es doch mal mit xppdbg.exe.
Vielleicht ist die Workbench ja das doch das Problem.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Carlo,

das ist es nicht. Auch wenn ich die exe direkt starte geht der in Folgeaufrufen nicht in die :start-Funktion rein.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Beginnt denn der Zähler in Zeile 0 meines Beispiels nicht bei jedem Tastendruck erneut bei 0 zu zählen?
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Das Problem ist, das oThread:active auf .T. stehen bleibt. Und damit geht der nicht neu in den :start rein.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Ja. Das stimmt.
Mit diesem Beispiel haben wir uns ja mächtig verfranzt.
Wenn die Schleife im Thread abläuft ist es so. Es muss noch ein ::quit() rein . Ich habs oben geändert.
Dann gehts. Auch mit der Workbench.
Da haben wir wirklich ein dummes Beispiel erwischt.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Naja, das ist ja das original Beispiel von Alaska.

Aber auch so klappt das nicht. Der bleibt jetzt in der DO WHILE-Schleife hängen im Sleep(1). Da kommt der nicht wieder raus.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Einen Versuch noch:

Jetzt in der Schleife an :active gehängt.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von brandelh »

Ich übergebe dem Thread ein Parameter per Referenz, in jeder Schleife fragt der Thread ab ob diese Variable auf Abbruch steht und beendet sich dann selbst.
Von außen einen Thread zu killen kann je nach Zustand und offener Resourcen übel enden.

Ich empfehle als Beispiel immer das Beispiel mit der Kaffeemaschine.
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Jan »

Auch 'ne Idee. Aber das teste ich heute nicht mehr durch.

Danke für die vielen Ideen zu dem Alaska-Sample.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Mit der terminate() Methode sendest du dem Thread ja nur den Wunsch zum Abbruch.
Wie und wann dass er der Thread das macht musst du ja dann selbst Programmieren.

Einfach so von aussen den Thread killen geht ja auch nicht.
Valar Morghulis

Gruss Carlo
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Tom »

Dafür verwendet man ein Signal-Object. Das funktioniert exzellent. Schaut Euch mal das Beispiel dafür an.
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Alaska-Sample myThread

Beitrag von AUGE_OHR »

hi,

die Method :start() ist für normale Thread,
die o:execute() - "Reservierte Methode für Subklassen der Thread-Klasse"

wenn du also mit eine "eigenen" Subclass und "terminate" arbeiten willst muss du die selbst definieren.
den Code welche durch die o:execute() Methode ausgeführt werden soll übergibt man per Parameter als Codeblock.
gruss by OHR
Jimmy
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Hallo Jan

ich habe mir mal eine Klasse entwickelt die funktionen zur Verfügung stellt um einfach Codeblöcke in Threads zu starten.
Natürlich kann in diesen Codeblöcken auch eine Funktion enthalten sein.

Für Aufgaben die länger laufen solltest du eine Public Var abfragen um auch ein geziehltes herunterfahren zu ermöglichen.
So wie du es im Beispiel in der Funktion testAusgabeLOOP() siehst.


Die Klasse nutzt Threadrecycling. Das verhindert dass zuviele beendete Threads den Stack sprengen, was damals mein Problem war.

Vielleicht hilft dir das ein wenig .....

Alles nötige im Anhang
Dateianhänge
threadclass.zip
(2.19 KiB) 141-mal heruntergeladen
Valar Morghulis

Gruss Carlo
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Alaska-Sample myThread

Beitrag von Tom »

Warst das nicht Du selbst, Carlo, der Probleme bekam, weil das Setzen einer PUBLIC als Steuerung für Threads verwendet wurde?

Ich kann nur empfehlen, ein Objekt der Signal-Klasse hierfür zu verwenden. Das initiiert man - bevorzugt als LOCAL - und gibt es dem Thread als Parameter mit. Das Threadobjekt selbst verwendet oSignal:Wait(nMillisecs) in Ersetzung für Sleep() oder ähnliches. Das beendet sich, wenn die Signal()-Methode des Signal-Objekts angesprochen wird. Da das Signal-Objekt entsprechend gekapselt ist, kann es auch nicht zu Belegungsirritationen kommen. Funktioniert sehr gut. Und das Thread-Objekt kann sich einfach beenden, wenn das Signal kommt.
Herzlich,
Tom
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2513
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 77 Mal

Re: Alaska-Sample myThread

Beitrag von ramses »

Hallo Tom

stimmt ich hatte Probleme mit Datenübergabe an Threads die in Public's gespeichert waren. Das waren aber Arrays in den Public's mit Daten.
Bei denen MEHRERE Threads gleichzeitig in die Datenarray gelesen/geschrieben hatten.
Ich gebe dir Recht mit der Signalklasse wäre das Threadbeenden auch wissenschaftlich wirklich korrekt.
Auch dies ist mit dem Beispiel problemlos möglich.

Jan wollte ein Beispiel mit Funktionen zum Aufrufen nicht mit Klassen.
Da war obiges Code Beispiel einfach das einzige das ich in meinem Archiv gefunden habe. Welches Threads mit Funktionen aufruft und aus diesen weitere Threads startet.
Es soll ja auch nur als Darstellung und Beispiel für eigne Weiterentwicklungen dienen.
Valar Morghulis

Gruss Carlo
Antworten