Leider kann ich immer noch nicht mit Threads umgehen.
Folgendes will ich umsetzen:
- Funktion erstellt einen Thread und übergibt eine Struktur
- Thread fängt an zu Arbeiten und updated Informationen in der Struktur
- Eine andere Funktion kann Informationen aus der Struktur lesen während der Thread noch läuft
- Thread kann jederzeit abgebrochen werden
Wie kann ich das umsetzten?
(Semaphores, Mutex ...)
[Hilfe] Threads wie?
Re: [Hilfe] Threads wie?
In der PB-Hilfe unter CreateSemaphore() findest du unten ein Beispielcode. Damit wird sichergestellt, dass die globale NewList immer von einer Prozedur zugegriffen oder geändert wird.
Den Code kannst du übernehmen. Der einzige Unterschied ist nur, dass du keine NewList verwendest, sondern eine Struktur.
Den Code kannst du übernehmen. Der einzige Unterschied ist nur, dass du keine NewList verwendest, sondern eine Struktur.
Re: [Hilfe] Threads wie?
Danke @RSBasic leider versteh ich nur Bahnhof.
Was ich versuche zu realisieren:
Was ich versuche zu realisieren:
Code: Alles auswählen
Structure TASK_STRUCT
Thread.i
Semaphore.i
Count.i
State.i
EndStructure
Procedure.i Task(*Task.TASK_STRUCT)
With *Task
While Not \Count = 100
Delay(2000)
\Count + 1;<- Wie schützen? Damit die GatTaskState() Funktion nicht dazwischen funkt!?
Wend
\State = #True;<- Task fertig! Wie schützen?
EndWith
EndProcedure
Procedure.i CreateTask();<- Gibt eine neuen Task zurück (Struktur)
Protected *Task.TASK_STRUCT
Protected Thread.i
*Task = AllocateStructure(TASK_STRUCT)
If *Task
With *Task
\Semaphore = CreateSemaphore()
If \Semaphore
\Thread = CreateThread(@Task(),*Task)
If \Thread
ProcedureReturn *Task
Else
FreeSemaphore(\Semaphore)
FreeStructure(*Task)
EndIf
EndIf
EndWith
FreeStructure(*Task)
EndIf
EndProcedure
Procedure.i GetTaskCount(*Task.TASK_STRUCT)
Debug *Task\Count;<- Wie auf den Thread korrekt zugreifen?
EndProcedure
Procedure.i GetTaskState(*Task.TASK_STRUCT)
Debug *Task\State;<- Wie auf den Thread korrekt zugreifen?
EndProcedure
Procedure.i EndTask(*Task.TASK_STRUCT)
Protected Count.i
If *Task\State = #True;<- Wie auf den Thread korrekt zugreifen?
Count = *Task\Count
FreeSemaphore(*Task\Semaphore)
FreeStructure(*Task)
ProcedureReturn Count
Else
;-> Wie kann ich den Thread abbrechen und beenden wenn er noch läuft?
EndIf
EndProcedure
Global Task.i
Global Exit.i
Task = CreateTask()
If Task
Repeat
GetTaskCount(Task)
If GetTaskState(Task)
EndTask(Task)
Exit = #True
EndIf
Until Exit
EndIf
Re: [Hilfe] Threads wie?
- Semaphoren sind eher da um zwischen Threads zu steuern. Verwende lieber einen Mutex um Daten zu schützen.
- Ein zusätzliches Feld Running ermöglicht den Thread von außen zu beenden.
- zwischen jedem Count+1 wird auch anderen Threads eine Zugriffsmöglichkeit gegeben, deswegen ist das While jetzt nur ein If und die Schleife ist außen drum, der Mutex wird pro Schleifendurchgang gelockt, und noch ein Delay(1) damit main zwischendurch eine Chance zum Zugriff hat.
- dein FreeStructure() in CreateTask() wäre übrigens doppelt aufgerufen worden.
- wie EndTask() aussehen soll bin ich mir nicht sicher. Ich würde das wohl eher aufteilen in WaitTask(), EndTask(), FreeTask() o.d.g., so dass man z.b. den Task beenden/abbrechen, danach aber immer noch state/count abfragen, und dann den Speicher separat freigeben kann.
- Ein zusätzliches Feld Running ermöglicht den Thread von außen zu beenden.
- zwischen jedem Count+1 wird auch anderen Threads eine Zugriffsmöglichkeit gegeben, deswegen ist das While jetzt nur ein If und die Schleife ist außen drum, der Mutex wird pro Schleifendurchgang gelockt, und noch ein Delay(1) damit main zwischendurch eine Chance zum Zugriff hat.
- dein FreeStructure() in CreateTask() wäre übrigens doppelt aufgerufen worden.
- wie EndTask() aussehen soll bin ich mir nicht sicher. Ich würde das wohl eher aufteilen in WaitTask(), EndTask(), FreeTask() o.d.g., so dass man z.b. den Task beenden/abbrechen, danach aber immer noch state/count abfragen, und dann den Speicher separat freigeben kann.
Code: Alles auswählen
Structure TASK_STRUCT
Thread.i
Mutex.i
Count.i
State.i
Runnning.i
EndStructure
Declare.i GetTaskRunning(*Task.TASK_STRUCT)
Procedure.i Task(*Task.TASK_STRUCT)
Protected taskRunning
taskRunning = GetTaskRunning(*Task)
While taskRunning
LockMutex(*Task\Mutex)
With *Task
If Not \Count = 10
Debug "+"
Delay(100)
\Count + 1
Else
\State = #True
\Runnning = #False
EndIf
EndWith
UnlockMutex(*Task\Mutex)
Delay(1)
taskRunning = GetTaskRunning(*Task)
Wend
EndProcedure
Procedure.i CreateTask()
Protected *Task.TASK_STRUCT
Protected Thread.i
*Task = AllocateStructure(TASK_STRUCT)
If *Task
With *Task
\Mutex = CreateMutex()
If \Mutex
\Runnning = #True
\Thread = CreateThread(@Task(),*Task)
If \Thread
ProcedureReturn *Task
Else
FreeMutex(\Mutex)
EndIf
EndIf
EndWith
FreeStructure(*Task)
EndIf
EndProcedure
Procedure.i GetTaskCount(*Task.TASK_STRUCT)
Protected taskCount
LockMutex(*Task\Mutex)
taskCount = *Task\Count
UnlockMutex(*Task\Mutex)
ProcedureReturn taskCount
EndProcedure
Procedure.i GetTaskState(*Task.TASK_STRUCT)
Protected taskState
LockMutex(*Task\Mutex)
taskState = *Task\State
UnlockMutex(*Task\Mutex)
ProcedureReturn taskState
EndProcedure
Procedure.i GetTaskRunning(*Task.TASK_STRUCT)
Protected taskRunning
LockMutex(*Task\Mutex)
taskRunning = *Task\Runnning
UnlockMutex(*Task\Mutex)
ProcedureReturn taskRunning
EndProcedure
Procedure.i EndTask(*Task.TASK_STRUCT)
Protected Count.i
If GetTaskState(*Task) = #True
Count = GetTaskCount(*Task)
Else
Count = -1 ; (z.b.)
EndIf
LockMutex(*Task\Mutex)
*Task\Runnning = #False
UnlockMutex(*Task\Mutex)
WaitThread(*Task\Thread)
FreeMutex(*Task\Mutex)
FreeStructure(*Task)
ProcedureReturn Count
EndProcedure
Global Task.i
Global Exit.i
Task = CreateTask()
If Task
Repeat
Debug "main: " + GetTaskCount(Task)
If GetTaskState(Task)
EndTask(Task)
Debug "main: exit"
Exit = #True
EndIf
Delay(1)
Until Exit
EndIf
Zuletzt geändert von #NULL am 17.09.2018 14:03, insgesamt 1-mal geändert.
Re: [Hilfe] Threads wie?
Vielen Dank hat mir geholfen#NULL hat geschrieben:- Semaphoren sind eher da um zwischen Threads zu steuern. Verwende lieber einen Mutex um Daten zu schützen.
- Ein zusätzliches Feld Running ermöglicht den Thread von außen zu beenden.
- zwischen jedem Count+1 wird auch anderen Threads eine Zugriffsmöglichkeit gegeben, deswegen ist das While jetzt nur ein If und die Schleife ist außen drum, der Mutex wird pro Schleifendurchgang gelockt, und noch ein Delay(1) damit main zwischendurch eine Chance zum Zugriff hat.
- dein FreeStructure() in CreateTask() wäre übrigens doppelt aufgerufen worden.
- wie EndTask() aussehen soll bin ich mir nicht sicher. Ich würde das wohl eher aufteilen in WaitTask(), EndTask(), FreeTask() o.d.g., so dass man z.b. den Task beenden/abbrechen, danach aber immer noch state/count abfragen, und dann den Speicher separat freigeben kann.
...
Re: [Hilfe] Threads wie?
Ich habe noch etwas korrigiert in EndTask() :
War vorher ... = #True, was keinen Sinn macht, der Thread soll ja zum Abbruch bewegt werden anstatt stur fertig zu zählen.
Code: Alles auswählen
*Task\Runnning = #False