Seite 1 von 1
Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 20:19
von Jan
Kann mir jemand sagen, wie ich einen bestimmten Thread aus einem anderen heraus beenden kann? Ich kann den mit dem Threadnamen identifizieren, aber ich glaube, das hilft nicht. Aber anhand dem könnte ich den halt identifizieren (was ist das eigentlich für ein Deutsch?
).
jan
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 20:34
von Martin Altmann
Jan,
Du musst in dem Thread einfach eine Methode haben (z.B. :stop()), die (im Prinzip) ein quit aufruft.
Und diese Methode rufst Du von außen auf.
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 20:53
von Jan
Hallo Martin,
soweit war ich auch schon
Und wie rufe ich die Methode für genau diesen Thread von außen auf?
Jan
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 21:00
von Martin Altmann
Nun,
ich denke, Du weißt den Threadnamen? Dann einfach oThread:stop()!
Anbei mal mein animierter Mauszeiger:
Code: Alles auswählen
CLASS RunDog FROM Thread
PROTECTED:
VAR terminated
VAR aniAct
EXPORTED:
VAR workCounter
INLINE METHOD init
::Thread:init()
::terminated := .F.
::aniAct := 1010
RETURN self
INLINE METHOD stop
RETURN ( ::terminated := .T. )
METHOD execute, checkTermination
ENDCLASS
// Diese Methode wird im Thread ausgeführt
METHOD RunDog:execute
do while .not. ::terminated
oApp:setPointer(,::aniAct,XBPWINDOW_POINTERTYPE_ICON)
::aniAct += 10
if ::aniAct > 1060
::aniAct := 1010
endif
sleep( 15 )
::checkTermination()
enddo
RETURN self
// Diese Methode prüft ob der Thread abgebrochen werden muß
// und terminiert ihn gegebenenfalls
METHOD RunDog:checkTermination
IF ::terminated
::terminated := .F.
oApp:setPointer( , 0, XBPWINDOW_POINTERTYPE_SYSPOINTER )
::quit()
ENDIF
RETURN self
Gestartet wird der Thread im Prinzip von außen wie folgt:
und gestoppt:
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 21:12
von Jan
Das heißt, ich muß eine eigene Klasse schreiben dafür? Denn: Meine Threads laufen alle parallel, und die Variablennamen sind alle LOCAL in den jeweils aufrufenden Funktionen.
Jan
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 21:20
von Martin Altmann
Hallo Jan,
Du kannst keinen Thread von außen aus einem anderen Thread heraus direkt beenden - nur indirekt!
Das quit muss in dem jeweiligen Thread erfolgen, der beendet werden soll. Also musst Du (analog zu meinem Beispiel oder dem 2. Beispiel in der Hilfe zu Threads) vorgehen.
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 21:53
von Jan
Martin, das ist mir schon klar. Mir ist aber nicht klar, wie ich da ran komme. Ich würde mir das ja gerne einfach machen mit Thread(cName):stop(). Aber das geht ja wohl nicht.
Jan
Re: Anderen Thread beenden
Verfasst: Di, 09. Feb 2010 22:04
von Martin Altmann
Jan,
Du kannst nicht von außen den Thread stoppen. Du kannst dem Thread nur von außen signalisieren, dass er sich beenden soll.
Wie Du das machst, bleibt Dir überlassen!
Entweder rufst Du von außen eine Methode auf, die eine Membervariable setzt, die Du während Deiner Threadinternen Verarbeitung immer wieder abfragst (wie im 2. Beispiel zur Hilfe zum Thema Threads) oder ob Du von außerhalb eine PUBLIC Variable setzt, die Du während Deiner Threadinternen Verarbeitung immer wieder abfragst oder ob Du mit einer anderen Variante arbeitest (Datenbankeintrag, Farbe eines Pixels an einer bestimmten Koordinate in Deinem Fenster,....) bleibt Dir überlassen.
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Mi, 10. Feb 2010 2:31
von AUGE_OHR
Jan hat geschrieben:Kann mir jemand sagen, wie ich einen bestimmten Thread aus einem anderen heraus beenden kann? Ich kann den mit dem Threadnamen identifizieren...
ich habe alle Thread Objecte in ein Array aufgenommen.
Wenn ich was von den will schicke ich ein PostAppEvent() an den betreffenden Thread.
Code: Alles auswählen
#define XbeE_StopThread xbeP_User+100
PostAppEvent(XbeE_StopThread,,,myThreadObject)
und im Thread dann
Code: Alles auswählen
DO WHILE .NOT. lExit
nEvent := AppEvent( @mp1, @mp2, @oXbp, nTimeOut)
DO CASE
CASE nEvent == xbe_None // Timeout
EXIT
CASE nEvent == XbeE_StopThread
EXIT
Re: Anderen Thread beenden
Verfasst: Mi, 14. Feb 2018 18:34
von Klaus Schuster
Hallo Martin,
welches Objekt soll oApp enthalten? setAppWindow()? Ausgeführt wird der Thread, zeigt aber nichts an.
Re: Anderen Thread beenden
Verfasst: Mi, 14. Feb 2018 19:14
von Martin Altmann
Hallo Klaus,
bei mir ist das das Hauptfenster - also das eigentliche Programm.
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Mi, 14. Feb 2018 19:31
von georg
Hallo, Jan -
grundsätzlich kannst Du einen Thread nur beenden, wenn er sich beenden lassen will: also muss der Thread einen Event-Loop haben, der abgefragt wird. Dazu kommt ein User-Event, das programmweit als Signal gilt "Thread beenden".
Jetzt kommen die Vorlieben der einzelnen Programmierer zum Tragen. Ich habe eine eigene Thread-Klasse abgeleitet, die ich mittels einer Include-Datei und einem
auf meine Thread-Klasse mappe. Die enthält eine Liste aller aktiven Threads, sowie einen Link zum jeweiligen Fenster (kein Thread ohne eigenes Fenster). Für die Inter-Thread-Kommunikation schicke ich dann das entsprechende User-Event an das Fenster des betreffenden Threads.
@Martin: ich bin bisher nicht auf die Idee gekommen, es mit dem Thread-Objekt selbst zu versuchen
Is natürlich einfacher ...
Also: von Hause aus kann Xbase++ das nicht, aber mit den vorhandenen Hausmitteln kann man sich etwas basteln, um das Problem elegant zu lösen.
Re: Anderen Thread beenden
Verfasst: Mi, 14. Feb 2018 19:46
von Klaus Schuster
Hallo Georg,
'kein Thread ohne Fenster' würde die Einsatzmöglichkeiten sehr einschränken. Threads können im Hintergrund E-Mails versenden, Berechnungen ausführen, Daten prüfen, usw. ohne ein eigenes Fenster zu haben. Ich neigen eher zum ungekehrten Schluss: Kein Fenster ohne eigenen Thread!
Re: Anderen Thread beenden
Verfasst: Mi, 14. Feb 2018 20:02
von georg
Hallo, Klaus -
bitte korrekt lesen:
Jetzt kommen die Vorlieben der einzelnen Programmierer zum Tragen.
auf meine Thread-Klasse mappe. Die enthält eine Liste aller aktiven Threads, sowie einen Link zum jeweiligen Fenster (kein Thread ohne eigenes Fenster).
Diese Aussage bezieht sich auf meine Programme - dort hat das bis heute sehr gut funktioniert. Aber auch Deiner Aussage
Kein Fenster ohne eigenen Thread!
kann ich zustimmen!
Re: Anderen Thread beenden
Verfasst: Mi, 14. Feb 2018 21:18
von Tom
Der Aussage mag man zustimmen, aber als Regel ist das gefährlicher Unsinn. Modulmodale Fenster haben in eigenen Threads nichts verloren, und Modalität hat ihren Zweck. Threads sind schon geil, aber zu viel Geilheit verdirbt den Spaß.
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 7:45
von Herbert
Klaus Schuster hat geschrieben: ↑Mi, 14. Feb 2018 19:46
'kein Thread ohne Fenster' würde die Einsatzmöglichkeiten sehr einschränken. Threads können im Hintergrund E-Mails versenden, Berechnungen ausführen, Daten prüfen, usw. ohne ein eigenes Fenster zu haben.
Genau da liegt die Idee der eigenen Thread-Programmierung: Etwas im Hintergrund erledigen ohne dass der Anwender etwas davon merkt und seine Arbeit dadurch nicht betroffen ist.
https://de.wikipedia.org/wiki/Thread_(Informatik)
Klaus Schuster hat geschrieben: ↑Mi, 14. Feb 2018 19:46Ich neigen eher zum ungekehrten Schluss: Kein Fenster ohne eigenen Thread!
Da bin ich gar nicht einverstanden.
Ein Thread läuft in sich geschlossen. Daher ist ein Thread, welcher GUI-Elemente verwendet, in der Regel nicht sinnvoll. Ein Bildaufbau u.ä. ist hier als Ausnahme zu sehen, um das Entstehen eines Fensters unabhängiger zu machen. Oder der Thread verarbeitet etwas, was nur während der Lebzeit dieses Fensters gilt. Nur weiss der Thread nicht, wann der User dieses Fenbster schliesst.
Windows selber arbeitet auch mit Threads (siehe Wiki-Link) und mit eigener Programmierung funkt ihr da hinein. Ich zweifle, ob viele Threads das Programm wirklich effektiver machen kann, im Gegenteil, wie auch Tom bemerkt:
Tom hat geschrieben: ↑Mi, 14. Feb 2018 21:18
aber als Regel ist das gefährlicher Unsinn. Modulmodale Fenster haben in eigenen Threads nichts verloren, und Modalität hat ihren Zweck. Threads sind schon geil, aber zu viel Geilheit verdirbt den Spaß.
Modale Fenster sollten ohnehin in einem schlauen Programm nie oder nur ganz selten (Datensicherung usw.) vorkommen.Sonst müssten wir dann mal über Design sprechen.
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 8:15
von Jan
Bei meinen Kunden lasse ich normalerweise nur Hintergrundprozesse als eigener Thread laufen. Wie die Abfrage nach neuen internen Nachrichten, die dann in einem Infofenster aufgeführt werden. Oder eine Videoüberwachung, wo jede Kamera in einem eigenen Thread läuft.
Allerdings habe ich eine eigene Software, die stark in Tabpages strukturiert ist. Und hier ist jede Tabpage ein eigener Thread, das habe ich vor ca. 10 Jahren einfach mal so umgesetzt bei der Umstellung von Clipper auf Xbase++. Ob ich das heute noch genau so stringent durchziehen würde kann ich nicht sagen. Manche der Tabpages stellen Auswertungen zusammen und geben die danach aus - da ist es gut, das die als Thread laufen, man kann währenddessen gut in anderen Tabpages weiter arbeiten. Andere geben nur aus oder dienen der Datenerfassung - ob da ein Thread sinnvoll ist mag zumindest diskussionswürdig sein.
Werden in einem Thread aber Dialoge geöffnet (modal oder wie auch immer), laufen die dann aber nicht in eigenen Threads. Ich wollte es dann doch auch nicht übertreiben.
Jan
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 8:17
von Martin Altmann
Moin Klaus,
Klaus Schuster hat geschrieben: ↑Mi, 14. Feb 2018 18:34Ausgeführt wird der Thread, zeigt aber nichts an.
zurück zu Deiner eigentlichen Frage:
In meiner Ressourcedatei sind sechs Mauszeiger hinterlegt - diese haben die IDs 1010 - 1060 (in Zehnersprüngen). Das Programm zeigt also einen der Mauszeiger an, wartet dann einen Moment und zeigt den nächsten an. Das kannst Du Dir wie ein langsam durchlaufendes Daumenkino vorstellen.
Damit das bei Dir funktioniert, musst Du also:
::aniAct und das Intervall an Deine Gegebenheiten anpassen
einzelne Mauszeiger Deiner Ressourcedatei hinzufügen.
Hier mal meine Bildchen in passender Reihenfolge:
- Hundilein_01.png (491 Bytes) 11024 mal betrachtet
- Hundilein_02.png (524 Bytes) 11024 mal betrachtet
- Hundilein_03.png (531 Bytes) 11024 mal betrachtet
- Hundilein_04.png (525 Bytes) 11024 mal betrachtet
- Hundilein_05.png (504 Bytes) 11024 mal betrachtet
- Hundilein_06.png (509 Bytes) 11024 mal betrachtet
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 8:23
von brandelh
Da die Xbase++ GUI in einem eigenen Thread läuft, ist es schlicht nicht nötig jedem Fenster noch einen eigenen zu verpassen.
Anders sieht das für alte Clipper Anwendungen aus, die - bisher systembedingt - nicht gleichzeitig laufen konnten, nun aber alles nebeneinander können sollen.
Solche XbpCrt() oder VIO Fenster kann man mit Threads einfach trennen, jeder mit "seinen" Arbeitsbereichen und "private" Variablen.
Ich habe immer einen Thread je Anwendung (GUI) - der darf aber nicht wirklich lange blockiert werden, daher lagere ich Funktionen nach dem Debuggen (das geht ohne eigenen Thread viel einfacher) in eigene Threads aus. Gerade Schnittstellenabfragen, Druck-Routinen oder lange Auswertungen (mit eigenen Dateien) können die GUI blocken, die kommen dann in Threads, früher habe ich statt dessen oft sleep(001) genutzt.
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 8:27
von Herbert
Jan hat geschrieben: ↑Do, 15. Feb 2018 8:15
Bei meinen Kunden lasse ich normalerweise nur Hintergrundprozesse als eigener Thread laufen. Wie die Abfrage nach neuen internen Nachrichten, die dann in einem Infofenster aufgeführt werden. Oder eine Videoüberwachung, wo jede Kamera in einem eigenen Thread läuft.
Allerdings habe ich eine eigene Software, die stark in Tabpages strukturiert ist. Und hier ist jede Tabpage ein eigener Thread, das habe ich vor ca. 10 Jahren einfach mal so umgesetzt bei der Umstellung von Clipper auf Xbase++. Ob ich das heute noch genau so stringent durchziehen würde kann ich nicht sagen. Manche der Tabpages stellen Auswertungen zusammen und geben die danach aus - da ist es gut, das die als Thread laufen, man kann währenddessen gut in anderen Tabpages weiter arbeiten. Andere geben nur aus oder dienen der Datenerfassung - ob da ein Thread sinnvoll ist mag zumindest diskussionswürdig sein.
Werden in einem Thread aber Dialoge geöffnet (modal oder wie auch immer), laufen die dann aber nicht in eigenen Threads. Ich wollte es dann doch auch nicht übertreiben.
Ja, genau so macht das Sinn
Eh, Martin, was hat das Beenden eines Threads mit deinen Hunden gemeinsam?
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 8:41
von Martin Altmann
Viel - schau es dir an!
Der Thread wird gestartet und wechselt den Mauszeiger kontinuierlich! Irgendwann muss er damit ja mal aufhören - das wird ihm von außen signalisiert.
Schau Dir den Beitrag mal von Anfang an an - er ist schon uralt!
Viele Grüße,
Martin
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 8:46
von Klaus Schuster
Moin Leute,
@Herbert: Doch, doch, es macht sehr viel Sinn sogar. Sinnvoll z.B. parallel beliebig viele Kundendaten in beliebig vielen Masken bearbeiten zu können, oder schnell zwischen Kundenmaske und Tourenpflege hin und her schalten zu können. Alle Tabelle sind stets gekapselt, der Alias stets der Tabellenname, usw. Neben der Bedienerfreundlichkeit ist Datensicherheit ein großer Gewinn. Interessant sind die drei Dokument die Claton Jones vor ein Paar Jahren verfasst hat. Der Einsatz modaler Fenster sollte den Kunden zuliebe auf ein Minimum beschränkt bleiben.
@Georg: Sehe es mir nach, doch Dein Satz war so schön kräftig, dass ich ihn aufgreifen musste.
@Tom: Es ist eher eine lange gepflegte Zuneigung, denn ein stürmisch junger Antrieb... Danke, dass Du mir den Glauben zurückgegeben hast, dass Programierung doch auch Bezüge zum Leben hat.
@Martin: Einfach, Danke!
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 11:14
von brandelh
Herbert hat geschrieben: ↑Do, 15. Feb 2018 7:45
Ein Thread läuft in sich geschlossen. Daher ist ein Thread, welcher GUI-Elemente verwendet, in der Regel nicht sinnvoll.
Oder der Thread verarbeitet etwas, was nur während der Lebzeit dieses Fensters gilt. Nur weiss der Thread nicht, wann der User dieses Fenbster schliesst.
Dass ein Thread Infos über seinen Fortschritt anzeigt, ist schon sinnvoll, ich lese z.B. große Dateien ein.
Bei vielen Millionen Datensätzen ist ein Thread schon klasse um die GUI zu entlasten. Hier mal ein Beispiel, auch wie ich das mit den gegenseitigen Infos mache:
Code: Alles auswählen
* __DateiImport wurde mit XppFD grob erstellt und dann nachgebessert
CLASS _DateiImport FROM __DateiImport
PROTECTED:
VAR oThread ********************************* diese Variable enthält den Verweis im Fenster auf den Importthread, siehe CLOSE !!!
...
EXPORTED:
METHOD init
METHOD create
METHOD CLOSE
METHOD DateiImportieren
...
ENDCLASS
*---------------------------------------------------------------------------
METHOD _DateiImport:close()
if ! ::oThread = NIL .and. ::oThread:active ******** das Fenster möchte schließen, aber Thread ist aktiv, was machen ???
*** in dem Beispiel erzwinge ich den Durchlauf .... man könnte das aber auch anders regeln
errbox("Einlesevorgang darf nicht abgebrochen werden !")
else
SetAppWindow( RootWindow())
::destroy()
endif
return self
*---------------------------------------------------------------------------
METHOD _DateiImport:DateiImportieren()
local cDatei
cDatei := ::sleDateiname:getData()
do case
case empty(cDatei)
errbox("Bitte Dateinamen eingeben oder mit ... ausw„hlen !")
SetAppFocus(::sleDateiname)
case empty(cDatei) .or. ! file( cDatei )
errbox("Datei: "+cDatei+" existiert nicht !"+CRLF+;
"Bitte Dateinamen eingeben oder mit ... ausw„hlen !")
SetAppFocus(::sleDateiname)
otherwise
**** alles disablen was nicht genutzt werden darf
::mleBericht:clear()
::pbDateiAuswahl:disable()
::pbImportStarten:disable()
::pbCancel:disable()
::pbBerichtDrucken:disable()
*** Thread anlegen, im Fenster Referenz hinterlegen und das Fenster selbst als Parameter an den Thread übergeben,
*** somit hat dieser Zugriff auf die GUI und VARS wenn er das braucht ...
::oThread := Thread():new()
::oThread:start("DoDateiImport", self , cDatei )
// Nach Ende des Threads setzt dieser die Controls wieder aktiv !
endcase
return self
Man könnte zum Abbruch z.B. eine iVAR ::Abbruch := .f. setzen und im Thread diese dann abfragen ... oXbp:Abbruch ????
Ich füttere die Anzeige mit Infos über die Anzahl eingelesener Datensätze ... und setze am Ende wieder enable auf die Controls.
Code: Alles auswählen
*---------------------------------------------------------------------------------------
function DoDateiImport(oXbp, cDatei) // cDatei ist Name der Textdatei
local nDB := NIL, ...
...
*** Zeienweise einlesen, dafür ist der TextReader() da
oTR := TextReader():new( cDatei )
if oTR:FError() <> 0
errbox("Fehler beim Öffnen der Datei !" + chr(13) + cDatei + chr(13) + oTR:ErrMsg())
return 1
endif
begin sequence
*** hier sollen die Daten rein, wichtig NEW öffnet die Datei in einem freien Selectbereich
USE (DatenVerzeichnis()+"xxxx") NEW
set index to (DatenVerzeichnis()+"xxxx")
*** ALIAS() ist für Menschen, PCs ziehen numerische SELECT() Werte vor, diese sind IMMER eindeutig !
nDB := Select()
...
nStart := seconds()
nFehler:= 0
nUnplausibel := 0
cTxt := ""
*** Infos an GUI übergeben !!!!
oXbp:sleFirmenName:SetData(cFirmenName) // wird in cDatei ermittelt
oXbp:sleFehlerAnzahl:SetData(alltrim(str(nFehler)))
*** MLE dient als Verlaufsanzeige, zunächst immer löschen, dann cTxt einfügen
*** ab einer gewissen länge wird gescrollt
oXbp:mleBericht:clear()
oXbp:mleBericht:insert(,cTxt)
*** gibt der GUI Zeit das anzuzeigen, sleep(0) kostet NICHTS, gibt aber Timeslice an nächsten Thread
sleep(0)
nZei := 0 // Textzeilenz„hler
nAnzByte := 0 // gelesene Byte aus Quelldatei
nAnz := 1 // hier wird mit einem angefangen, damit Anzeige besser aussieht
// dem Einlesen zu tun !
cTxt += dtoc(date())+" "+time()+" - "+alltrim(str(nAnz))+" Datensätze ..."+CRLF
oXbp:mleBericht:clear()
oXbp:mleBericht:insert(,cTxt)
nAnz := 0 // Eingelesen ist noch keiner, daher auf 0 setzen
nAnzByte := 0 // gelesene Byte
*** immer schön über die Anzahl der neuen Datensätze informieren
oXbp:sleSatzAnzahl:SetData(alltrim(str(nAnz)))
do while .t.
*** hier könnte man auch einen Abbruch einbauen !!!
if oXbp:Abbruch
msgbox( "von Benutzer abgebrochen" )
BREAK
endif
sleep(0)
*** ich nehme meine Textreader Klasse
cZei := oTR:GetLine()
nZei++
nAnzByte += len(cZei)+oTR:LenCrLf()
cSchl := upper(alltrim(left(cZei,10)))
*** Zeile einlesen, aufteilen speichern etc.
*** Anzahl anzeigen
nAnz++
oXbp:sleSatzAnzahl:SetData(alltrim(str(nAnz)))
if oTR:EOF()
exit
endif
enddo
nDauer := seconds() - nStart
beep()
cTxt += dtoc(date())+" "+time()+" - Es wurden "+if(nFehler=0,"keine",alltrim(transform(nFehler,"999,999,999,999")))+;
" Fehler gemeldet."+CRLF+;
dtoc(date())+" "+time()+" - "+alltrim(transform(nAnz,"999,999,999,999"))+;
" Datensätze wurden eingelesen (Dauer: "+alltrim(transform(nDauer/60,"9,999"))+" min)."+CRLF+;
...
*** Status ausgeben
oXbp:mleBericht:clear()
oXbp:mleBericht:insert(,cTxt)
end sequence
endif
oTR:destroy()
if (nDB)->(used())
(nDB)->(dbcloseArea()) // sicher ist sicher
oXbp:pbDateiAuswahl:enable()
oXbp:pbImportStarten:enable()
oXbp:pbCancel:enable()
oXbp:pbBerichtDrucken:enable()
endif
return nFehler
Re: Anderen Thread beenden
Verfasst: Do, 15. Feb 2018 11:34
von Tom
Herbert, ich kann mir nicht vorstellen, dass Du das wirklich so gemeint hast.
Es gibt mindestens zwei grundsätzlich unterschiedliche Verwendungsgebiete für Threads:
1. Als Container für ein (komplettes) Applikationsmodul. Dadurch lässt sich das Modul beliebig oft starten, ohne sich selbst zu behindern, alle Tabellenzugriffe sind gekapselt, Fenster können nichtmodal sein. Der Thread repräsentiert quasi einen eigenen Arbeitsplatz. Darin kann man dann auch alles tun, und natürlich jede Menge GUI. Dem GUI-Thread, der mit jeder Xbase++-Applikation mitläuft, ist es übrigens völlig egal, aus welchen oder wie vielen Threads heraus er verwendet wird. Solche Threads können auf globale Variablen der Applikation, globale Einstellungen und das Applikationsobjekt zugreifen, sind aber ansonsten abgeschlossen. Man kann ihnen aber als Parameter auch Informationen über andere Threads liefern.
2. Als paralleler Prozess. Der Klassiker sind Fortschrittsanzeigen, aber man kann auch Berechnungen, Downloads und andere Vorgänge auf mehrere Threads verteilen. Viele starten mit ihren Applikationen timergesteuerte Threads, die im Hintergrund Aufgaben überwachen. Auch solche Threads können mit der Oberfläche interagieren, was zum Beispiel bei Download- oder Verarbeitungsthreads sogar geboten ist. Man schaue sich das Upsize-Tool von Alaska an. Es startet je nach Tabellengröße bis zu vier Threads, die Tabellen in Chunks aufteilen und parallel nach PostGre migrieren. Alle vier Threads informieren dieselbe Oberfläche über ihre Aktivitäten (Fortschritt). Wenn alle vier Threads beendet sind, kann sich das Modul auch beenden.