Grundlagen: Threads in PB
PB stellt einem schon von Haus aus Funktionen zur Erstellung und Verwaltung von Threads bereit. Warum man Pause/Resume/Kill-Thread eher vermeiden sollte werde ich später im Tutorial noch erläutern.
Wie starte ich einen Thread in PB?
Dafür gibt es in PB den Befehl CreateThread(). Dieser erwartet den Pointer auf eine Procedure, und einen Übergabeparameter. Wobei wir schon bei der 1. Fehlerquelle währen:
Wichtig: Auch wenn euer Thread diesen Parameter nicht braucht müsst ihr ihn in die Procedurenparameter schreiben, sonst kommt es früher oder später zu einem Stack Fehler.
Nun starten wir unseren 1. Thread mit PB:
Code: Alles auswählen
; Thread Procedure. Parameter nicht vergessen!
Procedure MyThread(dummy)
MessageRequester("Thread", "Ich bin ein Thread")
EndProcedure
; Thread erstellen. Pointer auf Procedure mit @ ermitteln
Thread = CreateThread(@MyThread(), 0)
MessageRequester("Main", "Ich bin das Hauptprogramm")
Das war ja noch gar nicht so schwer. Nun wollen wir dem Thread aber natürlich auch Parameter übergeben, in diesem Beispiel den Text der angezeigt werden soll:
Wichtig: Sobald in Threads Strings vorkommen sollte man immer die Compiler-Option Thread-Safe verwenden.
Code: Alles auswählen
; Thread Procedure.
Procedure MyThread(*Text.s)
MessageRequester("Thread", *Text)
EndProcedure
; Thread erstellen. Pointer auf Procedure mit @ ermitteln
; Nun übergeben wir einen Parameter
Text.s = "Ich bin ein Thread"
Thread = CreateThread(@MyThread(), @Text)
MessageRequester("Main", "Ich bin das Hauptprogramm")
Auch bis hierher noch ganz einfach. Nun wollen wir aber meist nicht nur einen Parameter übergeben sondern mehrere. Da man an den Thread nur 1. übergeben kann lösen wir das ganze mit einer Struktur, in die wir alle Werte schreiben die wir brauchen, und an den Thread übergeben. Dafür schreiben wir uns eine kleine Launcher Procedure:
Code: Alles auswählen
; Thread Parameter
Structure Thread_Parameter
*Title ; Titel
*Text ; Text
Flags.i ;Parameter
EndStructure
; Thread Procedure
Procedure MyThread(*Thread.Thread_Parameter)
Protected Title.s, Text.s
Title.s = PeekS(*Thread\Title)
Text.s = PeekS(*Thread\Text)
MessageRequester(Title, Text, *Thread\Flags)
; Speicher aufräumen
FreeMemory(*Thread\Title)
FreeMemory(*Thread\Text)
FreeMemory(*Thread)
EndProcedure
; Thread - Starter
Procedure Thread_Launcher(Title.s, Text.s, Flags = 0)
; Neue Thread - Parameter anlegen
Protected *Thread.Thread_Parameter = AllocateMemory(SizeOf(Thread_Parameter))
; Thread - Paramter schreiben
; Ich verwende absichtlich keine nativen Strings in der Struktur da man diese
; manuell freigeben müsste, daher Speicherblöcke
*Thread\Title = AllocateMemory(StringByteLength(Title) + SizeOf(Character))
PokeS(*Thread\Title, Title)
*Thread\Text = AllocateMemory(StringByteLength(Text) + SizeOf(Character))
PokeS(*Thread\Text, Text)
*Thread\Flags = Flags
Thread = CreateThread(@MyThread(), *Thread)
ProcedureReturn Thread
EndProcedure
; Thread starten
Thread_Launcher("Thread","Ich bin ein Thread")
Thread_Launcher("Thread","Ich bin auch ein Thread")
MessageRequester("Main", "Ich bin das Hauptprogramm")
Wichtig: Der Thread muss seine Parameter am Ende immer freigeben, sonst ensteht ein Memory - Leak
So, nun haben wir bereit ein Anwendungsbeispiel: eine MessageBox die die Programmausführung nicht blockiert.
Das war ein kleines Beispiel wie man Threads in PB erstellen kann. Eigentlich sollte bis hierher alles klar sein, wenn es Fragen gibt nur her damit!