Seite 1 von 1
Thread-Programmierung [Erledigt]
Verfasst: Mo, 25. Jun 2012 10:40
von UliTs
Hallo allerseits,
ich möchte in einem Programmteil selbigen beenden, wenn der Benutzer eine Zeitlang keine Eingaben getätigt hat.
Deshalb habe ich einen Thread zur "Überwachung" eingeführt. Sobald die Zeit abgelaufen ist, soll dieser Thread mittels "Keyboard" ein ESC-Zeichen in den Tastaturpuffer des Programmteils schreiben. Geht das überhaupt und wenn ja, wie?
Uli
Re: Thread-Programmierung
Verfasst: Mo, 25. Jun 2012 11:04
von brandelh
In welchem Wartezustand bist du denn ?
@ GET kann man besser mit clear gets verlassen ...
Bei einer Schleife würde ich eine Flag-Variable für die Abbruchbedingung vorziehen, diese könnte per Funktion(static) oder als Parameter des Threadaufrufs verfügbar sein.
PostAppEvent() kann man ja das Ziel übergeben, wenn das ein Control oder ein Dialog ist (auch als Parameter ?) sollte das gehen.
Re: Thread-Programmierung
Verfasst: Mo, 25. Jun 2012 11:06
von georg
Guten Morgen, Uli -
ich gehe davon aus, dass Du zwei Threads verwendest. Du startest den Überwachungsthread #2 aus dem normalen Programmteil # und übergibst eine Referenz auf das Thread-
Objekt #1.
Stellst Du dann fest, dass die Zeit abgelaufen ist, sendest Du ein Event an das Thread-
Objekt #1:
Den Event-Loop im Thread-
Objekt #1 musst Du so anpassen, dass dieses Event abgefangen wird, um dann darauf zu reagieren:
Code: Alles auswählen
nEvent := AppEvent(...)
DO CASE
CASE nEvent == my_Event
//Programmteil beenden, z.B. durch KeyBoard(K_KESC)
OTHERWISE
oXbp:handleEvent(...)
ENDCASE
Allerdings denke ich, dass es schwierig ist, aus dem zweiten Thread den ersten zu überwachen, da Du zwei Event-Loops brauchst. Eventuell kannst Du die Abfrage ja in den Event-Loop des ersten Threads einbauen.
Gruss,
Georg
Re: Thread-Programmierung
Verfasst: Mo, 25. Jun 2012 11:14
von Tom
Warum überhaupt die Überwachung in einem gesonderten Thread? Einfach im Eventhandler die Zeit stoppen; wenn innerhalb von x Sekunden nichts passiert, also kein Event eintritt, schließt er, feddisch.
Re: Thread-Programmierung
Verfasst: Mo, 25. Jun 2012 11:20
von UliTs
Hallo Hubert, hallo Georg,
vielen Dank für Eure Antworten.
Da ich nach einer allgemeinen Lösung suche, funktionieren meines Erachtens beide Vorschläge nicht:
-
Bei Dir, Hubert, müsste ich jede Getlist-Variable Thread 2 übergeben.
Bei Dir, Georg, brauche ich Zugriff auf die Eventloop. Den habe ich leider nicht... Allerdings kann ich mittels PostAppEvent ja vielleicht auch direkt das ESC-Zeichen in die Event-Loop schreiben.
Dabei stellt sich die Frage: wie komme ich an die Thread-Variable des Haupt-Threads ran?
Uli
Re: Thread-Programmierung
Verfasst: Mo, 25. Jun 2012 11:29
von brandelh
Hi,
das aktuelle Thread-
Objekt:
ThreadObject() - Ermittelt das Thread-Objekt, das den aktuellen Thread verwaltet
Bei TOMs Vorschlag die Eventloop damit zu beauftragen hat man die größte Kontrolle.
Warum da meinst, diese übergeben zu müssen, ist mir nicht klar, in einem Programm das nur den Hauptthread hat,
gibt es nur eine, bzw. man ruft eine Funktion auf, die diesen Loop enthält.
Diese Funktion kann man einmal erstellen und dann einfach kopieren (oder in DLL auslagern ?).
Ich nutze eine solche Funktion um in schnellen Schleifen ab und an 1/100 Zeit an den Eventloop zu geben (Abbruch über GUI Button bzw. Anzeige von GUI Änderungen ...):
*-----------------------------------------------------------------------------
Code: Alles auswählen
FUNCTION DoEventLoop(nSeconds) // For Next Schleifen unterbrechen und Events verarbeiten !
local nBisSeconds, nEvent, mp1:=nil, mp2:=nil, oXbp:=nil
DEFAULT nSeconds to 0 // Standard ist endlose Ausführung
nBisSeconds := seconds() + nSeconds
DO WHILE .T.
nEvent := AppEvent( @mp1, @mp2, @oXbp, nSeconds)
do case
case nEvent = xbe_None
* nichts tun ist hier Standard
case nEvent = xbeP_Keyboard .and. mp1 == xbeK_F1 .and. HelpObject()==NIL
* xbeP_HelpRequest erscheinen für jede Xbp Instanz, also zu oft !
ShowNoHelp() // in ANW_MENU.PRG
otherwise
oXbp:handleEvent( nEvent, mp1, mp2 )
endcase
if nSeconds > 0 .and. nBisSeconds < seconds() // nur wenn keine endlose Ausführung
exit
endif
ENDDO
return nil
du müsstest hier anpassen:
case nEvent = xbe_None * nichts tun ist hier Standard
Re: Thread-Programmierung
Verfasst: Mo, 25. Jun 2012 12:51
von UliTs
Hallo Tom, Hubert, Georg,
danke für Eure Tipps.
Ich dachte schon, ich hätte die Lösung:
Code: Alles auswählen
PostAppEvent( xbeP_Keyboard/*nEvent*/,chr(27)/*mp1*/,/*mp2*/,ThreadObject()/*oXbp*/ )
Leider kommt aber die folgende Fehlermeldung:
- Betriebssystem : Windows XP 05.01 Build 02600 Service Pack 3
------------------------------------------------------------------------------
oError:args :
-> VALTYPE: N VALUE: 1048580
-> VALTYPE: C VALUE:
-> VALTYPE: U VALUE: NIL
-> VALTYPE: O CLASS: thread
oError:canDefault : N
oError:canRetry : N
oError:canSubstitute: J
oError:cargo : NIL
oError:description : Objekt nicht angemeldet
oError:filename :
oError:genCode : 103
oError:operation : postAppEvent
oError:osCode : 0
oError:severity : 2
oError:subCode : 4207
oError:subSystem : BASE
oError:thread : 1
oError:tries : 0
Ich kann mir den Luxus leisten und bei Time Out das Programm komplett beenden, was ich jetzt einfach (aus Zeitmangel) mache
.
Tom, gibt es eine Möglichkeit bei einem Hybridfenster die Eventloop zu beeinflussen?
Uli
Re: Thread-Programmierung [Erledigt]
Verfasst: Mo, 25. Jun 2012 13:13
von brandelh
Hi,
ein schönes Quit in Ehren ... aber sollte man vorher nicht erst alle Threads schließen ...
Bei deinem Beispiel oben fällt mir auf, dass du im Thread selbst das
ThreadObject() abfragst,
du solltest aber damit eigentlich vor dem Thread-Start den Main Thread abfragen und als Parameter an den Überwachungsthread übergeben.
Zudem sollte man wenn man schon einen Keyboard Event sendet, diesen nicht an einen Thread, sondern an das Control oder ein Fenster senden.
ein Quit ist sicher einfacher
Re: Thread-Programmierung [Erledigt]
Verfasst: Mo, 25. Jun 2012 14:21
von Tom
aber sollte man vorher nicht erst alle Threads schließen
Definiere:
Sollte.
Man muss
nicht. Eine Applikation, die diverse Module in Threads öffnet/anzeigt, kann auch mit QUIT beendet werden, ohne dass vorher alle Threads "geschlossen" werden.
Re: Thread-Programmierung [Erledigt]
Verfasst: Mo, 25. Jun 2012 14:34
von brandelh
Tom hat geschrieben:aber sollte man vorher nicht erst alle Threads schließen
Definiere:
Sollte.
Man muss
nicht. Eine Applikation, die diverse Module in Threads öffnet/anzeigt, kann auch mit QUIT beendet werden, ohne dass vorher alle Threads "geschlossen" werden.
schön das zu wissen, ich meine in der Anleitung stand was von syncronisieren, kann aber sein, dass das nur beim weiteren Betrieb nötig ist ... ich mache nicht soviel mit Threads
Re: Thread-Programmierung [Erledigt]
Verfasst: Mo, 25. Jun 2012 15:10
von Tom
Hallo, Hubert.
Man sollte natürlich grundsätzlich bei/vor jedem QUIT prüfen, ob kritische Prozesse laufen, deren nicht ordnungsgemäße Beendigung zu Problemen führen kann, aber ansonsten ist ein Thread als simpler Prozess zu betrachten, der halt parallel zu anderen läuft. Und all diese Prozesse werden meiner langjährigen Beobachtung nach problemlos beendet, wobei ich jetzt auch nicht so wirklich wüsste, welche Probleme ein von außen beendeter Thread generieren sollte, die nicht auch bei einer SDI-Applikation an gleicher Stelle auftreten könnten. Wenn in der App etwas geschieht, das geflissentlich überhaupt nicht abgebrochen werden sollte, muss man entsprechende Maßnahmen ergreifen. Man wird den Anwender allerdings niemals davon abhalten können, einfach den Netzstecker zu ziehen.
Die Synchronisation von Threads ist dafür gut, sie aufeinander warten zu lassen. Bei einem QUIT werden aber - hiervon unabhängig - ohnehin alle abgesch(l)ossen.