Threads Dialoge Menüsystem Windows
Moderator: Moderatoren
-
- Der Entwickler von "Deep Thought"
- Beiträge: 2828
- Registriert: Fr, 10. Feb 2006 9:51
- Wohnort: Aachen
- Hat sich bedankt: 259 Mal
- Danksagung erhalten: 12 Mal
- Kontaktdaten:
Threads Dialoge Menüsystem Windows
Hallo allerseits,
es geht um Fenster und Threads unter Windows und Xbase++. Ich würde dies gern besser verstehen .
Bei Xbase++ kann ich jederzeit neue Threads starten. Wenn ich es aber richtig verstanden habe, gibt es auch Threads, die durch Windows gestartet werden. Wenn ich z.B. ein Dialogfenster mit Menüsystem habe und einen Menüpunkt aufrufe, der eine längere Berechnung nach sich zieht, kann ich in dieser Zeit den Menüpunkt noch einmal aufrufen und die Berechnung wird dann ein zweites Mal (parallel) gestartet.
Ist es so, dass Windows bei jedem Aufruf eines neuen Menüpunkt einen neuen Thread startet?
Uli
es geht um Fenster und Threads unter Windows und Xbase++. Ich würde dies gern besser verstehen .
Bei Xbase++ kann ich jederzeit neue Threads starten. Wenn ich es aber richtig verstanden habe, gibt es auch Threads, die durch Windows gestartet werden. Wenn ich z.B. ein Dialogfenster mit Menüsystem habe und einen Menüpunkt aufrufe, der eine längere Berechnung nach sich zieht, kann ich in dieser Zeit den Menüpunkt noch einmal aufrufen und die Berechnung wird dann ein zweites Mal (parallel) gestartet.
Ist es so, dass Windows bei jedem Aufruf eines neuen Menüpunkt einen neuen Thread startet?
Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Mitglied XuG Cologne
Mitglied XuG Osnabrück
-
- Der Entwickler von "Deep Thought"
- Beiträge: 2824
- Registriert: Fr, 08. Feb 2008 21:29
- Hat sich bedankt: 95 Mal
- Danksagung erhalten: 13 Mal
Re: Threads Dialoge Menüsystem Windows
Hallo, Uli -
wenn Du mit Standard-Xbase-Befehlen arbeitest, hast Du (für Dich als Programmierer) nur einen einzigen Thread, in dem alle Anwendungen ablaufen.
Angenommen, Du hast einen Menü-Punkt "Kunden-Report". Wenn dieser Parameter abfragt und danach ohne weitere Interaktion mit dem Anwender auskommt, kannst Du während der Parameter-Abfrage weitere Funktionen/Prozeduren etc. aufrufen. Ab dem Moment. wo die Parameter-Abfrage beendet ist und der Report erstellt wird, kannst Du m.E. keinen Menü-Punkt auswählen.
Ich starte in einem solchen Fall eine Funktion, die ihrerseits einen Thread startet, der die entsprechende Funktion ausführt. Das sieht etwa so aus:
Mit dem Return von KundeReport() übernimmt der Haupt-Eventloop wieder die Kontrolle, und KundenReportThread() läuft als eigenständiger Thread parallel.
Es gibt im Hintergrund noch Threads des Xbase++-Laufzeitsystems, aber mit denen interagieren wir eigentlich nicht direkt.
Bezüglich paralleler Bearbeitung ist sicherzustellen, dass Deine Funktionen threadsafe sind. Wenn also die gleiche Funktion zweimal ausgeführt wird, dann "teilen" sich beide Threads die STATIC-Variablen in der Programm-Quelle bzw. der Funktion!
wenn Du mit Standard-Xbase-Befehlen arbeitest, hast Du (für Dich als Programmierer) nur einen einzigen Thread, in dem alle Anwendungen ablaufen.
Angenommen, Du hast einen Menü-Punkt "Kunden-Report". Wenn dieser Parameter abfragt und danach ohne weitere Interaktion mit dem Anwender auskommt, kannst Du während der Parameter-Abfrage weitere Funktionen/Prozeduren etc. aufrufen. Ab dem Moment. wo die Parameter-Abfrage beendet ist und der Report erstellt wird, kannst Du m.E. keinen Menü-Punkt auswählen.
Ich starte in einem solchen Fall eine Funktion, die ihrerseits einen Thread startet, der die entsprechende Funktion ausführt. Das sieht etwa so aus:
Code: Alles auswählen
FUNCTION KundenReport(xP1, xP2)
Local oThread
oThread := Thread():new()
oThread:atEnd := {|| dbCloseAll()}
oThread:start("KundenReportThread", xP1, xP2)
RETURN(.T.)
FUNCTION KundenReportThread(xP1, xP2)
...
RETURN(.T.)
Es gibt im Hintergrund noch Threads des Xbase++-Laufzeitsystems, aber mit denen interagieren wir eigentlich nicht direkt.
Bezüglich paralleler Bearbeitung ist sicherzustellen, dass Deine Funktionen threadsafe sind. Wenn also die gleiche Funktion zweimal ausgeführt wird, dann "teilen" sich beide Threads die STATIC-Variablen in der Programm-Quelle bzw. der Funktion!
Liebe Grüsse aus der Eifel,
Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
- brandelh
- Foren-Moderator
- Beiträge: 15695
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 65 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Re: Threads Dialoge Menüsystem Windows
Hallo Uli,
soweit ich weiß startet Windows eine EXE als eigenen Prozess.
Innerhalb der EXE muss diese selbst dafür sorgen neue Threads zu bilden.
Innerhalb von Xbase++ Anwendungen gibt es 3 Threads, die von der Runtime beim Start der EXE erstellt werden.
Der GUI Thread (im Hintergrund) kümmert sich um die Anzeige und antwortet Windows in sehr kurzer Zeit, damit dieses die Anwendung nicht als "blockiert" meldet.
Der zweite weiß ich aktuell nicht was genau der macht, eventuell der GC ?
Der dritte ist der MAIN() indem das Programm läuft. Egal ob du einen Button anklickst oder einen Menüpunkt wird alles im MAIN() Thread abgearbeitet.
Du kannst zwar eigene Threads machen und auch Fenstern eigene Threads zuordnen, aber automatisch geht da nichts.
PS: kommt leider ab und zu vor, der Desktop hängt ... und nach einiger Zeit die Meldung der Explorer (eigentlich der IE) musste neu gestartet werden ...
Die komplette Oberfläche ist ein Thread, wenn sich irgendwo ein Explorer aufhängt reißt er häufig den Desktop mit.
soweit ich weiß startet Windows eine EXE als eigenen Prozess.
Innerhalb der EXE muss diese selbst dafür sorgen neue Threads zu bilden.
Innerhalb von Xbase++ Anwendungen gibt es 3 Threads, die von der Runtime beim Start der EXE erstellt werden.
Der GUI Thread (im Hintergrund) kümmert sich um die Anzeige und antwortet Windows in sehr kurzer Zeit, damit dieses die Anwendung nicht als "blockiert" meldet.
Der zweite weiß ich aktuell nicht was genau der macht, eventuell der GC ?
Der dritte ist der MAIN() indem das Programm läuft. Egal ob du einen Button anklickst oder einen Menüpunkt wird alles im MAIN() Thread abgearbeitet.
Du kannst zwar eigene Threads machen und auch Fenstern eigene Threads zuordnen, aber automatisch geht da nichts.
PS: kommt leider ab und zu vor, der Desktop hängt ... und nach einiger Zeit die Meldung der Explorer (eigentlich der IE) musste neu gestartet werden ...
Die komplette Oberfläche ist ein Thread, wenn sich irgendwo ein Explorer aufhängt reißt er häufig den Desktop mit.
Gruß
Hubert
Hubert
-
- Der Entwickler von "Deep Thought"
- Beiträge: 2828
- Registriert: Fr, 10. Feb 2006 9:51
- Wohnort: Aachen
- Hat sich bedankt: 259 Mal
- Danksagung erhalten: 12 Mal
- Kontaktdaten:
Re: Threads Dialoge Menüsystem Windows
Das heißt, dass obige Verhalten wird durch Threads des Xbase-Laufzeitsystems erzeugt?Georg hat geschrieben:...
Es gibt im Hintergrund noch Threads des Xbase++-Laufzeitsystems, aber mit denen interagieren wir eigentlich nicht direkt.
...
Das kann ich mir kaum vorstellen.
Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Mitglied XuG Cologne
Mitglied XuG Osnabrück
- Tom
- Der Entwickler von "Deep Thought"
- Beiträge: 9358
- Registriert: Do, 22. Sep 2005 23:11
- Wohnort: Berlin
- Hat sich bedankt: 101 Mal
- Danksagung erhalten: 361 Mal
- Kontaktdaten:
Re: Threads Dialoge Menüsystem Windows
Hallo, Uli.
Es gibt, wie Hubert ausgeführt hat, einige Threads, die vom Xbase++-Laufzeitsystem (mit)gestartet werden, zum Beispiel der Thread für das Eventhandling (EVM), für die Interaktion mit der Oberfläche (UI) und den Garbage Collector (GC). Ansonsten sind alle Threads, die es darüber hinaus gibt, von Dir oder von der von Dir eingesetzten Zusatzbibliothek (TD und eXpress++ erzeugen beispielsweise beim ersten Aufruf ihrer Eventloops Threads für Tooltips). Für das Neuzeichnen von UI-Elementen ist der UI-Thread verantwortlich, und zwar ganz egal, wie viele MDI-Fenster es in Deiner App gibt. Die natürlich, wenn Du sie in Threads erzeugst, wiederum jeweils einen besitzen - aber nur dann, wenn Du das tatsächlich explizit tust. Sonst nicht.
Es gibt, wie Hubert ausgeführt hat, einige Threads, die vom Xbase++-Laufzeitsystem (mit)gestartet werden, zum Beispiel der Thread für das Eventhandling (EVM), für die Interaktion mit der Oberfläche (UI) und den Garbage Collector (GC). Ansonsten sind alle Threads, die es darüber hinaus gibt, von Dir oder von der von Dir eingesetzten Zusatzbibliothek (TD und eXpress++ erzeugen beispielsweise beim ersten Aufruf ihrer Eventloops Threads für Tooltips). Für das Neuzeichnen von UI-Elementen ist der UI-Thread verantwortlich, und zwar ganz egal, wie viele MDI-Fenster es in Deiner App gibt. Die natürlich, wenn Du sie in Threads erzeugst, wiederum jeweils einen besitzen - aber nur dann, wenn Du das tatsächlich explizit tust. Sonst nicht.
Herzlich,
Tom
Tom
-
- Der Entwickler von "Deep Thought"
- Beiträge: 2824
- Registriert: Fr, 08. Feb 2008 21:29
- Hat sich bedankt: 95 Mal
- Danksagung erhalten: 13 Mal
Re: Threads Dialoge Menüsystem Windows
Hallo, Uli -
ich habe aufgezeigt, wie man einen Thread selbst aufsetzt.
Dann habe ich darauf hingewiesen, dass die Laufzeit-Umgebung selbst mit Threads operiert, mit denen wir aber nicht interagieren können.
Deine ursprüngliche Frage habe ich so verstanden "geht das automatisch?" Nein, geht nicht, aber es gibt Konstellationen, die den Eindruck erwecken, dass so etwas automatisch ginge:
- der Anwender startet einen Menü-Punkt
- der Menü-Punkt erfragt Parameter (hier hat der Event-Loop wieder die Kontrolle)
- während dieser Zeit (wenn der Event-Loop die Kontrolle hat) kannst Du diesen (oder einen anderen Menü-Punkt) ebenfalls starten
- sobald der erste der Dialoge "loslegt" (z.B. durch das Klicken eines XbpPushButton()), verliert der Event-Loop die Kontrolle und andere Funktionen in Deinem Standard-Thread "stehen" bis der Menü-Punkt abgearbeitet ist;
- der Event-Loop bekommt wieder die Kontrolle.
Wenn Menü-Punkte so verzahnt ablaufen, kann es erscheinen (!), dass Xbase++ selbst Threads erzeugt, aber das ist nicht der Fall. Ein Thread startet quasi "nackt", d.h. vorher geöffnete Dateien sind im Thread NICHT geöffnet (darum kann ich am Ende eines Threads auch ein dbCloseAll() ausführen, da nur die Dateien in diesem Thread geschlossen werden).
Willst Du Threads, musst Du sie selbst programmieren.
ich habe aufgezeigt, wie man einen Thread selbst aufsetzt.
Dann habe ich darauf hingewiesen, dass die Laufzeit-Umgebung selbst mit Threads operiert, mit denen wir aber nicht interagieren können.
Deine ursprüngliche Frage habe ich so verstanden "geht das automatisch?" Nein, geht nicht, aber es gibt Konstellationen, die den Eindruck erwecken, dass so etwas automatisch ginge:
- der Anwender startet einen Menü-Punkt
- der Menü-Punkt erfragt Parameter (hier hat der Event-Loop wieder die Kontrolle)
- während dieser Zeit (wenn der Event-Loop die Kontrolle hat) kannst Du diesen (oder einen anderen Menü-Punkt) ebenfalls starten
- sobald der erste der Dialoge "loslegt" (z.B. durch das Klicken eines XbpPushButton()), verliert der Event-Loop die Kontrolle und andere Funktionen in Deinem Standard-Thread "stehen" bis der Menü-Punkt abgearbeitet ist;
- der Event-Loop bekommt wieder die Kontrolle.
Wenn Menü-Punkte so verzahnt ablaufen, kann es erscheinen (!), dass Xbase++ selbst Threads erzeugt, aber das ist nicht der Fall. Ein Thread startet quasi "nackt", d.h. vorher geöffnete Dateien sind im Thread NICHT geöffnet (darum kann ich am Ende eines Threads auch ein dbCloseAll() ausführen, da nur die Dateien in diesem Thread geschlossen werden).
Willst Du Threads, musst Du sie selbst programmieren.
Liebe Grüsse aus der Eifel,
Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
- brandelh
- Foren-Moderator
- Beiträge: 15695
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 65 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Re: Threads Dialoge Menüsystem Windows
nur zur Sicherheit, welches Programm mit einem Menü meinst du hier ?UliTs hat geschrieben: Wenn ich z.B. ein Dialogfenster mit Menüsystem habe und einen Menüpunkt aufrufe, der eine längere Berechnung nach sich zieht,
kann ich in dieser Zeit den Menüpunkt noch einmal aufrufen und die Berechnung wird dann ein zweites Mal (parallel) gestartet.
Ein Xbase++ oder ein anderes ?
Wenn du aus dem Explorer eine EXE startest, kannst du das normalerweise mehrfach tun, weil die meisten EXE das zulassen.
Der Explorer startet für jede EXE einen neuen Prozess. Mehr nicht.
Es ist mit vielen Sprachen sehr einfach eine Exe zu schreiben, die gerade NICHT mehr reagiert nach dem du eine langsame Bearbeitung gestartet hast.
Häufig liest man, dass man die EventLoop() nicht überlasten darf, wenn du dort z.B. sleep(10) einbaust, wirst du sehen, dass Standardmäßig das komplette Programm lahmt !
Und wenn ein Menüpunkt z.B. eine Endlosschleife startet, wird sich das Programm auch nicht mehr bedienen lassen.
Gruß
Hubert
Hubert
- AUGE_OHR
- Marvin
- Beiträge: 12906
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 45 Mal
Re: Threads Dialoge Menüsystem Windows
hi,
1.) Der Thread will was an oMain schicken ( PostAppEvent )
2.) wenn ein Thread aktive ist und ein weiteres Mal aufgerufen wird schalte ich um auf "den" Thread
3.) oMain will dem Thread was mitteilen ( z.b. QUIT -> alle Threads schliessen )
ich habe die Technik bei PDRLFU angewendet wo man beliebig viele Detail Fenster im eigenen Thread öffnen kann.
wenn in einem Detail Fenster z.b. ein Verweis angeklickt wird sendet der Thread einen UserDef Event an oMain wo das Browse läuft.
nachdem das Browse nun synchronisiert wurde wird ein neues Detail Fenster als Thread geöffnet ( oder er schaltet auf ein geöffneten Thread )
so ähnlich mache ich es auch aber ich benötige mehr "Kontrolle" und eine Kommunikationen wenn ich mit mehreren Threads arbeite.georg hat geschrieben:Code: Alles auswählen
FUNCTION KundenReport(xP1, xP2) Local oThread oThread := Thread():new() oThread:atEnd := {|| dbCloseAll()} oThread:start("KundenReportThread", xP1, xP2) RETURN(.T.) FUNCTION KundenReportThread(xP1, xP2) ... RETURN(.T.)
1.) Der Thread will was an oMain schicken ( PostAppEvent )
2.) wenn ein Thread aktive ist und ein weiteres Mal aufgerufen wird schalte ich um auf "den" Thread
3.) oMain will dem Thread was mitteilen ( z.b. QUIT -> alle Threads schliessen )
ich habe die Technik bei PDRLFU angewendet wo man beliebig viele Detail Fenster im eigenen Thread öffnen kann.
wenn in einem Detail Fenster z.b. ein Verweis angeklickt wird sendet der Thread einen UserDef Event an oMain wo das Browse läuft.
nachdem das Browse nun synchronisiert wurde wird ein neues Detail Fenster als Thread geöffnet ( oder er schaltet auf ein geöffneten Thread )
Code: Alles auswählen
PROCEDURE KundThread( cAction, nSeekRec, oGUIbrowse )
LOCAL bBlock
LOCAL oKundThread
LOCAL lBig := IF( APPDESKTOP() :Currentsize() [2] > 601, .T., .F. )
LOCAL nHigh := 0
LOCAL aSize := { 800, 600 - nHigh }
LOCAL aPP := { { XBP_PP_BGCLR, GRA_CLR_WHITE } }
LOCAL nPosi := 0
LOCAL aThread := SP_Thread()
LOCAL nLen := LEN( aThread )
LOCAL aLoben
LOCAL aPos := { 0, 500 }
aSize := SP_MainSize()
alOben := { 0, APPDESKTOP() :Currentsize() [2] - aSize[2]}
// did we have any Thread
IF nLen > 0
// is there any "KUNDEN" in it
IF ASCAN( aThread, { | x | x[ ID_WHO ] == "KUNDEN" } ) > 0
// find MAX position
AEVAL( aThread, { | x | IF( x[ ID_WHO ] == "KUNDEN", ;
Versatz( aPos, x ), ;
NIL ) } )
// Position berechnen
...
ENDIF
ENDIF
IF VALTYPE( nSeekRec ) = "N"
nPosi := ASCAN( aThread, { | x | x[ ID_REC ] == nSeekRec .AND. ;
x[ ID_WHO ] == "KUNDEN" } )
// Thread läuft schon
IF nPosi > 0
SETAPPWINDOW( aThread[ nPosi ] [ ID_OBJ ] )
aThread[ nPosi ] [ ID_OBJ ] :toFront()
SETAPPFOCUS( aThread[ nPosi ] [ ID_OBJ ] )
RETURN
ENDIF
ELSE
IF VALTYPE( cAction ) = "C"
DO CASE
CASE cAction = "NEU"
// hier die Aktionen
CASE ...
OTHERWISE
MSGBOX( "keine Record Nummer zum positionieren gefunden" )
RETURN
ENDCASE
ELSE
MSGBOX( "keine Action zum positionieren gefunden" )
RETURN
ENDIF
ENDIF
bBlock := { || PDRdetail( oGUIbrowse, NIL, aPos, aSize, aPP, .F., cAction, nSeekRec, oGUIbrowse),;
oGUIbrowse, NIL, aPos, aSize, aPP, .F., cAction, nSeekRec, oGUIbrowse }
oKundThread := Thread() :new()
oKundThread:start( bBlock )
SP_ThreadAdd( { nSeekRec, cAction, aPos, "", "KUNDEN" } )
RETURN
gruss by OHR
Jimmy
Jimmy