Aktuelle Zeit: 12.11.2019 23:43

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: [Hilfe] Threads wie?
BeitragVerfasst: 16.09.2018 12:25 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
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 ...)

_________________

Links:
PureBasic Discord
[ENGINE] 2D Engine Nautilus (Win)
[INCLUDE] GLFW 3.3 Library
[MODULE] Bass Library 2.4 (Win)
[LIBRARY] Hexi Binary2Hex (Win)



Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: [Hilfe] Threads wie?
BeitragVerfasst: 16.09.2018 12:32 
Offline
Admin
Benutzeravatar

Registriert: 05.10.2006 18:55
Wohnort: Deutschland::Berlin()
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.

_________________
BildBildBildBild BildBild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: [Hilfe] Threads wie?
BeitragVerfasst: 16.09.2018 16:38 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
Danke @RSBasic leider versteh ich nur Bahnhof.

Was ich versuche zu realisieren:
Code:
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

_________________

Links:
PureBasic Discord
[ENGINE] 2D Engine Nautilus (Win)
[INCLUDE] GLFW 3.3 Library
[MODULE] Bass Library 2.4 (Win)
[LIBRARY] Hexi Binary2Hex (Win)



Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: [Hilfe] Threads wie?
BeitragVerfasst: 16.09.2018 18:55 
Offline
Benutzeravatar

Registriert: 20.04.2006 09:50
- 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.
Code:
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

_________________
my pb stuff..
Bild..jedenfalls war das mal so.


Zuletzt geändert von #NULL am 17.09.2018 14:03, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: [Hilfe] Threads wie?
BeitragVerfasst: 17.09.2018 12:26 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
#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.
...


Vielen Dank hat mir geholfen :)

_________________

Links:
PureBasic Discord
[ENGINE] 2D Engine Nautilus (Win)
[INCLUDE] GLFW 3.3 Library
[MODULE] Bass Library 2.4 (Win)
[LIBRARY] Hexi Binary2Hex (Win)



Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: [Hilfe] Threads wie?
BeitragVerfasst: 17.09.2018 14:07 
Offline
Benutzeravatar

Registriert: 20.04.2006 09:50
Ich habe noch etwas korrigiert in EndTask() :
Code:
*Task\Runnning = #False

War vorher ... = #True, was keinen Sinn macht, der Thread soll ja zum Abbruch bewegt werden anstatt stur fertig zu zählen.

_________________
my pb stuff..
Bild..jedenfalls war das mal so.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: Google [Bot] und 1 Gast


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye