Ich versuche im Moment in meinem Spiel das "Hauptprogramm" von der GUI zu lösen und meine Erfahrungen mit Threads generell waren bisher eher als bescheiden zu betrachten.
Hier mal mein Beispielcode:
Code: Alles auswählen
EnableExplicit
Declare MyThread (*junk)
Structure THREADVars
tmutex.i
IsRunning.i;Statusvariable ob Thread noch läuft, soll von GUI überprüft werden.
;interne Variablen des Threads, nicht unbedingt mutexgeschützt
ExitThread.i;threadinternes Abbruchsignal
EndStructure
Structure GUIVars
gmutex.i
ThreadBreakSignal.i;"GUIWunsch" für Beenden des Threads, soll vom Thead überprüft werden
;interne Variablen der GUI, nicht unbedingt mutexgeschützt
;a.i
EndStructure
;Mutex
Define.i tmutex,gmutex
Define gvars.GUIVars, tvars.THREADVars
;Mutex erzeugen
tvars\tmutex= CreateMutex()
gvars\gmutex= CreateMutex()
Define Event.i
If OpenWindow(0, 0, 0, 300, 100, "GUI vs. Thread", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(1, 10, 10, 250, 20, "Thread läuft nicht")
ButtonGadget(2, 10, 40, 120, 20, "Starte Thread")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case 2
LockMutex(tvars\tmutex)
LockMutex(gvars\gmutex)
If tvars\IsRunning=0 ;wenn KEIN Thread läuft
gvars\ThreadBreakSignal=0
CreateThread(@MyThread(), 0)
SetGadgetText(2, "Beende Thread")
Else ;wenn Thread läuft
gvars\ThreadBreakSignal=1
EndIf
UnlockMutex(gvars\gmutex)
UnlockMutex(tvars\tmutex)
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow
EndIf
Procedure MyThread (*junk)
Shared gvars,tvars
Define.l start
Define.i ExitThread=0
LockMutex(tvars\tmutex)
tvars\IsRunning=1 ;wenn Thread läuft, dies nach aussen anzeigen
UnlockMutex(tvars\tmutex)
tvars\ExitThread=0
Repeat
;die "Alle 5 Sekunden Lang Schwer Beschäftigt ohne Abbruchmöglichkeit Simulation"
;trotz GUIwunsch wird Thread weiterlaufen
SetGadgetText(1, "Thread heavy")
start=ElapsedMilliseconds()
Repeat
Until ElapsedMilliseconds()>start+5000
;die "Alle 5 Sekunden Lang Leicht Beschäftigt Mit Abbruchmöglichkeit Simulation"
SetGadgetText(1, "Thread easy")
start=ElapsedMilliseconds()
Repeat
LockMutex(gvars\gmutex)
If gvars\ThreadBreakSignal=1 ;wenn GUI den Thread beenden will
tvars\ExitThread=1 ;setze threadinternes Abbruchsignal
EndIf
UnlockMutex(gvars\gmutex)
Until (ElapsedMilliseconds()>start+5000) Or (tvars\ExitThread=1)
Until tvars\ExitThread=1
;Aufräumen
LockMutex(tvars\tmutex)
tvars\IsRunning=0 ;wenn Thread beendet, dies nach aussen anzeigen
UnlockMutex(tvars\tmutex)
SetGadgetText(1, "Thread läuft nicht")
SetGadgetText(2, "Starte Thread")
EndProcedure
Ist dieses Konstrukt einigermaßen threadsave?
Und wie sieht es mit dem Zugriff auf die GUI aus dem Thread heraus aus? Ich beziehe mich mal auf jene Befehle die das Aussehen oder den Status der Controls verändern.
Ausserdem habe ich das Gefühl,dass man schnell mal gewillt ist im Thread eine Art Arbeitskopie von Variablen zu erzeugen, um dem mutexen etwas aus dem weg zu gehen
Mutton