ich habe einige Probleme mit Threads und entstehenden Deadlocks.
Folgendes Beispiel:
Ich habe in meinem Fall zwei Prozeduren. Die erste Prozedur "Gadget_erstellen()" erstellt und löscht Gadgets. Die zweite Prozedur "Gadget_anpassen()" passt Gadgets an. "Gadget_erstellen()" wird immer im Hauptthread aufgerufen und "Gadget_anpassen()" immer in einem zweiten Thread aufgerufen. Würde man jetzt keinen Mutex verwenden, so kommt es schnell zu Fehlern/Abstürze, da der zweite Thread Gadgets anpassen will, die ggf. im Hauptthread gerade entfernt wurden.
Nun setze ich einen Mutex ein (siehe Code), der das gleichzeitige Ausführen beider Prozeduren verhindern soll.
....folgendes Passiert:
- zweiter Thread sperrt Mutex
- Hauptthread pausiert anschließend an der Zeile: LockMutex(iMutex) und wartet auf die Freigabe
- zweiter Thread verarbeitet während dessen die Prozedur und bleibt beim Befehl SetGadgetText() stehen
-Deadlock-
Ich denke mal, dass SetGadgetText() ggf. eine Nachricht sendet oder auf irgendetwas wartet (eventuell ein WindowEvent()). Dieses wird ja nicht mehr aufgerufen, da der Hauptthread gesperrt wurde. ....bin mir aber nicht sicher.
hier ist mal ein Beispielcode:
Code: Alles auswählen
Declare Gadget_erstellen()
Declare Gadget_anpassen()
Declare MeinThread(*Parameter)
Global iGadget.i
Global iTextGadget_Main.i
Global iTextGadget_Thread.i
Global iMutex.i = CreateMutex()
OpenWindow(0, 0, 0, 200, 100, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
iTextGadget_Main = TextGadget(#PB_Any, 10, 80, 80, 20, "Main")
iTextGadget_Thread = TextGadget(#PB_Any, 100, 80, 80, 20, "Thread")
CreateThread(@MeinThread(), 0)
Repeat
If ElapsedMilliseconds() - Timer >= 1
Timer = ElapsedMilliseconds()
Counter_Main + 1
SetGadgetText(iTextGadget_Main, "Main: " + Str(Counter_Main))
Gadget_erstellen ()
EndIf
Until WaitWindowEvent(0) = #PB_Event_CloseWindow
Procedure MeinThread(*Parameter)
Protected Counter_Thread = 0
Repeat
Counter_Thread + 1
SetGadgetText(iTextGadget_Thread, "Thread: " + Str(Counter_Thread))
Gadget_anpassen()
ForEver
EndProcedure
Procedure Gadget_erstellen ()
LockMutex(iMutex)
If IsGadget(iGadget)
FreeGadget(iGadget)
EndIf
iGadget = ButtonGadget(#PB_Any, 50, 38, 100 ,20, "Button")
UnlockMutex(iMutex)
EndProcedure
Procedure Gadget_anpassen ()
If TryLockMutex(iMutex)
If IsGadget(iGadget)
SetGadgetText(iGadget, "irgendwas")
EndIf
UnlockMutex(iMutex)
EndIf
EndProcedure
Wichtig wäre mir, dass die aufgerufene Prozedur im Hauptthread "Gadget_erstellen ()" erfolgreich verarbeitet und nie übersprungen wird. Würde ich also ein TryLockMutex im Hauptthread verwenden, dann wäre zwar ein Deadlock nicht mehr möglich, aber die Prozedur würde dann übersprungen werden, bis irgendwann einmal ein Lock möglich wäre.
Die Prozedur im zweiten Thread ist fast nebensächlich. Das bedeutet es wäre nicht schlimm, wenn diese mal übersprungen oder abgebrochen wird. Sollte diese Prozedur aufgerufen werden, so muss diese auch komplett verarbeitet oder abgebrochen werden. --> also wäre sowas wie ein PauseThread() ungünstig.
Ich denke mal killthread() kommt auch nicht in Frage, wenn ich mir die Hilfe so ansehe.
Hat jemand eine Idee?
viele Grüße
SBond
