Threads Dialoge Menüsystem Windows

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Antworten
UliTs
Der Entwickler von "Deep Thought"
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

Beitrag von UliTs »

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
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
georg
Der Entwickler von "Deep Thought"
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

Beitrag von georg »

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:

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.)
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!
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
brandelh
Foren-Moderator
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

Beitrag von brandelh »

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.
Gruß
Hubert
UliTs
Der Entwickler von "Deep Thought"
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

Beitrag von UliTs »

Georg hat geschrieben:...
Es gibt im Hintergrund noch Threads des Xbase++-Laufzeitsystems, aber mit denen interagieren wir eigentlich nicht direkt.
...
Das heißt, dass obige Verhalten wird durch Threads des Xbase-Laufzeitsystems erzeugt?
Das kann ich mir kaum vorstellen.

Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
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

Beitrag von Tom »

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.
Herzlich,
Tom
georg
Der Entwickler von "Deep Thought"
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

Beitrag von georg »

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.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
brandelh
Foren-Moderator
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

Beitrag von brandelh »

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.
nur zur Sicherheit, welches Programm mit einem Menü meinst du hier ?
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
Benutzeravatar
AUGE_OHR
Marvin
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

Beitrag von AUGE_OHR »

hi,
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.)
so ähnlich mache ich es auch aber ich benötige mehr "Kontrolle" und eine Kommunikationen wenn ich mit mehreren Threads arbeite.

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
Antworten