Thread für Anfänger

Anfängerfragen zum Programmieren mit PureBasic.
Sommertv
Beiträge: 68
Registriert: 26.04.2019 10:31
Computerausstattung: Lenovo W500, Debian Stable, Purebasic 5.70 (momentan die Testversion)
Wohnort: Mühldorf am Inn

Thread für Anfänger

Beitrag von Sommertv »

Hallo,
ich taste mich langsam an Threads heran, hab dazu ein einfaches Beispiel im Netz gefunden und das erfolgreich abgeändert und erweitert.
Allerdings ist mir manches unklar, vielleicht kann mir das jemand erklären.

Code: Alles auswählen

Enumeration
 #FENSTER_HAUPT
 #LISTE_EINS
 #LISTE_ZWEI
 #KNOPF_1
 #KNOPF_2
EndEnumeration

Procedure TextEinfuegen(i)
 For x.i = 1 To 250
 AddGadgetItem(#LISTE_EINS, -1, Str(x))
; Debug "Thread1 " + Str(x)  
 Delay(100)
 Next x
EndProcedure

Procedure TextEEinfuegen(i)
 For x.i = 1 To 250
 AddGadgetItem(#LISTE_ZWEI, -1, Str(x))
; Debug "Thread2 " + Str(x)   
 Delay(100)
 Next x
EndProcedure

#FLAGS = #PB_Window_SystemMenu | #PB_Window_ScreenCentered

If OpenWindow(#FENSTER_HAUPT, 0, 0, 290, 240, "Thread Test", #FLAGS)
 ListViewGadget(#LISTE_EINS, 10, 10, 130, 150)
 ListViewGadget(#LISTE_ZWEI, 150, 10, 130, 150)
 ButtonGadget(#KNOPF_1, 95, 170, 100, 20, "Knopf1 Test")
 ButtonGadget(#KNOPF_2, 95, 200, 100, 20, "Knopf2 Test")
 
 Repeat
   Ereignis.i = WaitWindowEvent()

 Select Ereignis
 Case #PB_Event_Gadget
   
Select EventGadget()
   Case #KNOPF_1
    Thread1.i = CreateThread(@TextEinfuegen(), 1)
    
   Case #KNOPF_2 
   Thread2.i = CreateThread(@TextEEinfuegen(), 1)
   
EndSelect
 EndSelect
 Until Ereignis = #PB_Event_CloseWindow
 
EndIf

End
Wenn ich Ereignis.i vor WaitWindowEvent entferne und in der Case Anweisung nur CreateThread schreibe hängt der Code bzw wird nicht ausgeführt. Es sollte doch eigentlich reichen, den Thread zu erzeugen.
Warum muss ich dem Thread die 1 mitgeben? Ich habs ohne versucht aber dann kommt eine Fehlermeldung.
Ich könnt das zwar als so gegeben hinnehmen, möcht aber immer gern die Hintergründe erfahren...

Dank im Vorab
Kurt
Wenn einem die einfachen Dinge net einfallen, klappt's meistens umständlich...
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Thread für Anfänger

Beitrag von mk-soft »

Beim Aufruf der Thread-Procedure wird IMMER ein Parameter übergeben. Auch wenn dieser nicht gebraucht wird.
Somit muss IMMER die Procedure auch ein Parameter haben.

P.S.
Das mit AddGadgetItem(#LISTE_EINS, -1, Str(x)) aus einem Thread heraus funktioniert nur unter Windows
Nicht das du dich wunders das es unter Linux oder macOS zum Crash führt.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Thread für Anfänger

Beitrag von mk-soft »

Kleinen Tip was man mit diesen Parameter machen kann.

Update

Code: Alles auswählen

;-TOP

CompilerIf Not #PB_Compiler_Thread
  CompilerError "Use Compiler-Option ThreadSafe!"
CompilerEndIf

Structure udtThreadDefaultData
  ; Default
  ThreadID.i
  UserID.i
  Exit.i
EndStructure

Structure udtThreadData Extends udtThreadDefaultData
  ; Data
  Count.i
EndStructure

Structure udtThreadData2 Extends udtThreadDefaultData
  ; Data
  Text.s
EndStructure

Procedure StartThread(*Data.udtThreadDefaultData, *Procedure)
  If Not IsThread(*Data\ThreadID)
    *Data\ThreadID = CreateThread(*Procedure, *Data)
  EndIf
  ProcedureReturn *Data\ThreadID
EndProcedure

Procedure StopThread(*Data.udtThreadDefaultData)
  Protected time = ElapsedMilliseconds()
  If IsThread(*Data\ThreadID)
    *Data\Exit = #True
    While IsThread(*Data\ThreadID)
      If ElapsedMilliseconds() - time > 1000
        Debug "Thread UserID" + *Data\UserID + " reagiert nicht -> KillThread"
        KillThread(*Data\ThreadID)
        Break
      EndIf
      Delay(10)
    Wend
    *Data\ThreadID = 0
    *Data\Exit = #False
  EndIf
EndProcedure

Procedure MyThread(*Data.udtThreadData)
  Protected c
  
  While c < *Data\Count
    If *Data\Exit
      Break
    EndIf
    c + 1
    Debug "UserID = " + *Data\UserID + " Count = " + c
    Delay(100)
  Wend
  
EndProcedure

Procedure MyBlockedThread(*Data.udtThreadData2)
  Protected c
  Debug *Data\Text
  Repeat
    Delay(100)
  ForEver
  
EndProcedure
  
Global th1.udtThreadData
th1\UserID = 1
th1\Count = 20

Global th2.udtThreadData
th2\UserID = 2
th2\Count = 10000

Global th3.udtThreadData2
th3\UserID = 3
th3\Text = "Block Thread"

StartThread(th1, @MyThread())
Delay(50)
StartThread(th2, @MyThread())
Delay(50)
StartThread(th3, @MyBlockedThread())

Delay(5000)
StopThread(th1)
StopThread(th2)
StopThread(th3)
KillThread sollte nur im Notfall verwendet werden!
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Sommertv
Beiträge: 68
Registriert: 26.04.2019 10:31
Computerausstattung: Lenovo W500, Debian Stable, Purebasic 5.70 (momentan die Testversion)
Wohnort: Mühldorf am Inn

Re: Thread für Anfänger

Beitrag von Sommertv »

Guten Morgen,
danke... das muss ich erst mal analysieren, das ein oder andere ändern und schauen wie was reagiert.
Tast mich da langsam ran, dann versteh ich auch die Zusammenhänge...
Weil du schreibst AddGadgetItem funktioniert unter Linux nicht, meinst du Standalone?
Weil innerhalb des Compilers läuft der Code bei mir einwandfrei...

Schöne Grüsse
Kurt
Wenn einem die einfachen Dinge net einfallen, klappt's meistens umständlich...
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Thread für Anfänger

Beitrag von Bisonte »

Sommertv hat geschrieben:Guten Morgen,
danke... das muss ich erst mal analysieren, das ein oder andere ändern und schauen wie was reagiert.
Tast mich da langsam ran, dann versteh ich auch die Zusammenhänge...
Weil du schreibst AddGadgetItem funktioniert unter Linux nicht, meinst du Standalone?
Weil innerhalb des Compilers läuft der Code bei mir einwandfrei...

Schöne Grüsse
Kurt
Es funktioniert. Zufällig. Man muss sich bei Verwendung mit Threads hauptsächlich merken :

1. Das Programm selbst ist schon ein Thread (MainThread)
2. Interaktionen mit Fenstern/Gadgets nur in dem Thread in dem die Fenster/Gadgets erstellt wurden.
3. Globale Variablen schützen!

Fehlersuche ist schwierig.
Fenster und Gadgets sollte man von einem Thread aus mit "Events" steuern. PostEvent() ist da der Schlüssel.
Das ist essentiell... egal welches OS.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Thread für Anfänger

Beitrag von mk-soft »

Schau mal in meine Signatur...

ThreadToGUI
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Sommertv
Beiträge: 68
Registriert: 26.04.2019 10:31
Computerausstattung: Lenovo W500, Debian Stable, Purebasic 5.70 (momentan die Testversion)
Wohnort: Mühldorf am Inn

Re: Thread für Anfänger

Beitrag von Sommertv »

@Bisonte:

Hmmm, versteh ich das jetzt richtig?
Ich muss also einen Button, Textfeld usw innerhalb des Threads definieren, dann kann ich es gefahrlos bearbeiten.
Dann könnt ich doch die Position des Hauptfensters abfragen und z.B. das Textfield aus dem Thread exakt darunter positionieren.
Oder einen Button einblenden und wieder verschwinden lassen...
Verzeiht die dummen Fragen...
Wenn einem die einfachen Dinge net einfallen, klappt's meistens umständlich...
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Thread für Anfänger

Beitrag von Bisonte »

Damit ist gemeint : Ein Fenster und seine Gadgeterstellung, sowie die Eventverarbeitung von diesem erstellten gehören in einen! Thread.
Also komplett.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Antworten