Seite 2 von 3
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 16:15
von jacdelad
Code: Alles auswählen
Global thread
Procedure MyThread(dummy)
Repeat
Delay(1000)
Debug "Thread lebt noch!"
ForEver
EndProcedure
OpenWindow(0,0,0,300,200,"MyWindow",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ScrollBarGadget(0,10,10,280,20,0,100,5)
CreateThread(@MyThread(),0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case 0
Debug GetGadgetState(0)
EndSelect
EndSelect
ForEver
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 16:41
von Re42
Es läuft eine For-Next-Schleife und aus dieser heraus wird immerwieder neu der Thread aufgerufen mit Prd(*x). Der Thread selber sieht dann so aus:
Code: Alles auswählen
Procedure Prd(*x)
Shared starttime
Shared time
Shared ggst.d
Shared svl.d
Shared count
starttime = ElapsedMilliseconds()
Repeat
time = ElapsedMilliseconds()
ExamineKeyboard()
Select event
Case #PB_Event_Menu
Select EventMenu()
Case #PB_Key_Space
time = 1200
EndSelect
Until (time - starttime) > 1100
count = 0
EndProcedure
Dadrunter stehen die Anweisungen für den Thread, das ScrollBarGadget und das BindGadgetEvent:
Code: Alles auswählen
ScrollBarGadget(1,1010,25,20,363,1,100,10,#PB_ScrollBar_Vertical) ; 1,1010,19,20,375,1,100,10
CreateThread(@Prd(),1)
BindGadgetEvent(1, @BindVScrollDatas())
Das ScrollBarGadget läßt sich aber nicht bewegen, solange der Thread läuft. Liegt das an dem Aufruf aus der For-Next-Schleife heraus?
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 16:49
von jacdelad
Du musst schon einen lauffähigen Code posten.
...allerdings ist die Aussage, dass der Thread immer wieder neu gestartet wird schon etwas seltsam. Und im Thread hat EventMenu() nichts zu suchen, das gehört in die Schleife für Events. Ebenso ExamineKeyboard, das ist dort mit 99%-iger Sicherheit falsch.
Poste mal einen lauffähigen Code. Und vielleicht auch mal, was genau gemacht werden soll. Ich hab die Vermutung, dass du vielleicht gar keinen Extra-Thread brauchst.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 16:52
von NicTheQuick
Re42 hat geschrieben: 22.09.2022 15:36
Die Sache hat noch einen weiteren Haken, denn, wenn der Thread läuft, ist das ScrollBarGadget blockiert. Oder kommt man da irgendwie raus?
Und noch etwas möchte ich schon lange beseitigen, auch wenn das jetzt nicht zum Thema gehört: Wie erreicht man in einer Procedure oder Subroutine, daß man auch dann das Fenster bewegen oder schließen kann? Das ist so häßlich, wenn dann jedesmal "Keine Rückmeldung" kommt. Es ist ja wahrscheinlich verpöhnt, Event = WaitWindowEvent(x) mehr als nur einmal in den Code zu schreiben.
Danke.
Du machst sicherlich grundlegend etwas falsch. Am besten postest du mal deinen Code, der die Probleme verursacht.
In der Regel reicht eine Ereignisschleife mit 'WaitWindowEvent()'. Threads blockieren diese ja nicht, dafür sind sie da.
Edit: Hoppla, ich hab die zweite Thread-Seite noch gar nicht gesehen.
Also in dem Fall schließe ich mich an: Ein lauffähiger Code wäre wichtig.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 16:59
von Re42
Der Aufruf des Threads erfolgt Xmal aus einer For-Next-Schleife heraus. Der Thread sieht so aus:
Code: Alles auswählen
Procedure Prd(*x)
Shared starttime
Shared time
Shared ggst.d
Shared svl.d
Shared count
starttime = ElapsedMilliseconds()
Repeat
time = ElapsedMilliseconds()
ExamineKeyboard()
Select event
Case #PB_Event_Menu
Select EventMenu()
Case #PB_Key_Space
time = 1200
EndSelect
If KeyboardReleased(#PB_Key_Space) And space = 1
space = 0
EndIf
If KeyboardPushed(#PB_Key_Space) And space = 0
StopSound(#PB_All)
space = 2
br = 1
esc = 1
Break
EndIf
Until (time - starttime) > 1100
count = 0
EndProcedure
Und noch ein paar Programmzeilen weiter unten:
Code: Alles auswählen
Procedure BindVScrollDatas()
Shared ggst.d
ggst.d = GetGadgetState(1)
svl.d = 91 - ggst.d ; 76 - ggst.d
SoundVolume(#PB_All,svl.d)
EndProcedure
ScrollBarGadget(1,1010,25,20,363,1,100,10,#PB_ScrollBar_Vertical)
ggst.d = GetGadgetState(1)
svl.d = 91 - ggst.d
SoundVolume(#PB_All,svl.d)
CreateThread(@Prd(),1)
BindGadgetEvent(1, @BindVScrollDatas())
Vielleicht ist ja dann das ScollBarGadget blockiert, weil der Thread jedesmal aus einer For-Next-Schleife heraus aufgerufen wird, ich weiß es nicht. Ich werde lauffähigen Code vorbereiten.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 17:09
von Re42
Ich werde etwas vorbereiten an Code-Beispiel, aber das schaffe ich jetzt nicht mehr. Nachher ist Dienst, wird also morgen.
Das mit dem zweiten Event = WaitWindowEvent(5) hatte ich gemacht, weil ich auch in der Procedure Abfragen brauche und weil das Fenster nicht "Keine Rückmeldung" ausgeben soll, wenn ich das versuche, zu bewegen, während eine Procedure oder Subroutine durchlaufen wird. In einer zweiten Schleife wird doch das Event = WaitWindowEvent(5) der Hauptschleife erst gar nicht mehr erreicht. Ich habe nie gewußt, wie man aus dem Dilemma anders raus kommen soll als mit Extra Event = WaitWindowEvent(5).
Danke nochmals.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 17:10
von NicTheQuick
Der Code ist so immer noch nicht lauffähig, ohne das man da Fenster und alles mögliche drum herum baut.
Aber grundlegend hast du Threads entweder falsch verstanden oder du willst da etwas machen, wozu es gar keine Threads benötigt. In der Regel startet man Threads nicht zig mal um das selbe zu machen, sondern man startet einen Thread und der läuft eben einfach weiter. Ein Thread ist ein Programmteil, der neben dem Hauptprogramm läuft. Wenn du ihn immer wieder startest bevor der letzte Thread sich selbst beendet hat, hast du irgendwann ganz viele Threads gleichzeitig laufen. Und es sieht so aus, dass dein Thread immer mindestens 1100 ms läuft.
Innerhalb des Threads wertest du außerdem Events aus, bzw. um genauer zu sein nutzt du die Variable 'event', die sowieso immer 0 ist. Außer sie ist global, aber das kann man in deinem Code nicht sehen, weil er eben unvollständig ist. Aber auch 'EventMenu()' gehört da nicht.
Eine Bitte an dich: Beantworte uns mal die Frage, was genau du erreichen möchtest. Damit ist es viel einfacher zum Ziel zu kommen als von hinten durch die Brust ins Auge Threads zu erklären.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 17:23
von Re42
Ich würde am liebsten gar keinen Thread laufen lassen müssen. Statt des Threads war da erst eine Procedure und die war auf jeden Fall vor jedem Neuaufruf auch wieder beendet.
Was ich erreichen will, ist, daß ich während des Abspielens von max. 20 Tönen hintereinander deren Lautstärke über ein ScrollBarGadhet regeln kann, ohne daß die Schleife stehen bleibt und damit dann auch das Abspielen der Töne. In einer For-Next-Schleife werden die Töne aus dem Array aufgerufen und die Abspiellänge der Töne wurde ursprünglich in einer Subroutine geregelt, um das nicht für jeden Ton extra schreiben zu müssen. Es gibt dann aber Probleme mit dem ScrollBarGadget, weil die Repeatschleife stehen bleibt, sobald ich da drauf klicke. Daher jetzt das Thema Thread.
Ich habe jetzt leider erstmal keine Zeit mehr. Ich melde mich später wieder. Danke.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 22.09.2022 17:27
von jacdelad
Aber bitte mit Code und einer Beschreibung, was dein Ziel ist. Sonst bin ich raus.
Re: Wie baut man einen Thread richtig auf?
Verfasst: 23.09.2022 12:07
von Re42
Ich habe jetzt mittlerweile mal einen lauffähigen Code zusammengestellt. Das Fenster ist zwar wesentlich kleiner als im Originalprogramm, aber es soll ja jetzt auch nur gezeigt werden, was prinzipiell passiert:
Über die Leertaste kann im Originalprogramm das Abspielen / Stoppen von Tönen ausgelöst werden. Das habe ich jetzt ersetzt durch Zahlen. Mir ist klar, dass ich mir in dem Fall Select - EndSelect auch hätte sparen können, aber beim Abspielen von Tönen geht das nicht anders, weil nicht einfach PlaySound(zahl) geschrieben werden kann, da muß jedesmal die jeweilige Zahl in der Klammer stehen.
Die Subroutine regelt die Abspiellänge mit Timer. Nicht mit Delay, damit über die Leertaste die Wiedergabe auch jederzeit wieder gestoppt werden kann.
Über das ScrollBarGadget kann im Originalprogramm die Lautstärke geregelt werden. Und jetzt das Problem dabei: Sobald das ScrollBarGadget angeklickt wird, bleibt die Repeat-Schleife in der Subroutine stehen. In der Praxis klingt dann der zuletzt wiedergegebene Ton aus und die Lautstärkeregelung ist so nicht gerade vom feinsten. Wie kann das beseitigt werden?
Euch wird auffallen, dass in der Subroutinen-Repeat-Schleife auch nochmal drin steht event = WaitWindowEvent(5) und auch nochmal ExamineKeyboard(). Die Abfrage in der Hauptschleife ist ja dann aber abgekapselt. Geht das ggf. auch anders? Das kann doch kein Geheimwissen sein, bitte erklärt mir, wie das ggf. besser geht. Gestern hatte ich auch mit Prozedur experimentiert, aber das war Murks, daher jetzt Subroutine.
Hier nun der Code:
Code: Alles auswählen
If InitSprite() = 0
MessageRequester("InitSprite failed", "")
EndIf
If InitMouse() = 0
MessageRequester("InitMouse failed","")
EndIf
If InitKeyboard()
;MessageRequester("InitKeyboard failed", "")
EndIf
If OpenWindow(1,0,0,130,413,"",#PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered) = 0 ; 412
;MessageRequester("OpenWindow failed", "")
EndIf
If OpenWindowedScreen(WindowID(1),0,0,110,413) = 0
MessageRequester("OpenWindowedScreen failed", "")
EndIf
Procedure BindVScrollDatas()
Shared ggst.d
ggst.d = GetGadgetState(1)
svl.d = 91 - ggst.d
EndProcedure
ScrollBarGadget(1,110,25,20,363,1,100,10,#PB_ScrollBar_Vertical) ; 1,1010,19,20,375,1,100,10
SetGadgetState(1,46)
ggst.d = GetGadgetState(1)
BindGadgetEvent(1, @BindVScrollDatas())
Dim zahl.d(9)
For i = 1 To 5
zahl.d(i-1) = i
Next
Repeat
event = WaitWindowEvent(5)
Select event
Case #PB_Event_LeftClick
;...
EndSelect
ExamineKeyboard()
If KeyboardReleased(#PB_Key_Space) And space = 2
space = 0
EndIf
If KeyboardPushed(#PB_Key_Space) And space = 0
space = 1
For i = 1 To 5
zahl = zahl.d(i-1)
Select zahl
Case 1
Debug zahl
Gosub Spiellaenge
If br = 1
br = 0
i = 5
Break
EndIf
Case 2
Debug zahl
Gosub Spiellaenge
If br = 1
br = 0
i = 5
Break
EndIf
Case 3
Debug zahl
Gosub Spiellaenge
If br = 1
br = 0
i = 5
Break
EndIf
Case 4
Debug zahl
Gosub Spiellaenge
If br = 1
br = 0
i = 5
Break
EndIf
Case 5
Debug zahl
Gosub Spiellaenge
If br = 1
br = 0
i = 5
Break
EndIf
EndSelect
Next
EndIf
Until event = #PB_Event_CloseWindow
End
Spiellaenge:
starttime = ElapsedMilliseconds()
Repeat
event = WaitWindowEvent(5)
ExamineKeyboard()
time = ElapsedMilliseconds()
If KeyboardReleased(#PB_Key_Space) And space = 1
space = 0
EndIf
If KeyboardPushed(#PB_Key_Space) And space = 0
space = 2
br = 1
Break
EndIf
If KeyboardPushed(#PB_Key_Right) Or KeyboardPushed(#PB_Key_Up)
ggst.d = ggst.d - 0.3
If ggst < 0
ggst = 0
EndIf
SetGadgetState(1,ggst.d)
EndIf
If KeyboardPushed(#PB_Key_Left) Or KeyboardPushed(#PB_Key_Down)
ggst.d = ggst.d + 0.3
If ggst > 91
ggst = 91
EndIf
SetGadgetState(1,ggst.d)
EndIf
Until (time - starttime) > 1100
Return
Danke für weitere Hilfe.