Simple Thread Control

Share your advanced PureBasic knowledge/code with the community.
User avatar
mk-soft
Always Here
Always Here
Posts: 6240
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Simple Thread Control

Post by mk-soft »

It is sometimes asked how to control threads.
I have times a simple example created without special imported functions.

Maybe hate anyone more simple examples for beginners.

Update v1.03
- Update example with Semaphore

Code: Select all

;-TOP

; Comment:  Simple Thread Control 
; Author:   mk-soft
; Version:  v1.03
; Create:   22.11.2015
; Update:   01.09.2016

Enumeration 
  #thread_cmd_nothing
  #thread_cmd_start
  #thread_cmd_pause
  #thread_cmd_continue
  #thread_cmd_stop
EndEnumeration

Enumeration
  #thread_state_nothing
  #thread_state_startingup
  #thread_state_running
  #thread_state_pausing
  #thread_state_paused
  #thread_state_continued
  #thread_state_stopping
  #thread_state_stopped
  #thread_state_finished
EndEnumeration

Enumeration #PB_Event_FirstCustomValue
  #thread_event_state
EndEnumeration

Structure udtMyThread
  ; Header
  id.i
  signal.i
  cmd.i
  state.i
  ; Userdata
  counter.i
EndStructure

; ***************************************************************************************

Procedure ThreadState()
  
  Protected *this.udtMyThread
  
  *this = EventGadget()
  
  Select EventType()
    Case #thread_state_nothing
      StatusBarText(0, 0, "Nothing")
      
    Case #thread_state_startingup
      StatusBarText(0, 0, "Startingup")
      
    Case #thread_state_running
      StatusBarText(0, 0, "Running")
      
    Case #thread_state_pausing
      StatusBarText(0, 0, "Pause pending")
      
    Case #thread_state_paused
      StatusBarText(0, 0, "Paused")
      
    Case #thread_state_continued
      StatusBarText(0, 0, "Continued")
      
    Case #thread_state_stopping
      StatusBarText(0, 0, "Stopping")
      
    Case #thread_state_stopped
      StatusBarText(0, 0, "Stopped")
      
    Case #thread_state_finished
      StatusBarText(0, 0, "Finished")
      
  EndSelect
  
EndProcedure

Macro SendThreadState(This, State)
  PostEvent(#thread_event_state, 0, This, State)
EndMacro

; ***************************************************************************************

; Thread control macros

Macro MyStartThread(thread)
  If Not IsThread(thread\id)
    thread\id = CreateThread(@MyThread(), @thread1)
  EndIf
  thread\cmd = #thread_cmd_start
  If thread\signal
    SignalSemaphore(thread\signal)
  EndIf
EndMacro

Macro MyPauseThread(thread)
  thread\cmd = #thread_cmd_pause
EndMacro

Macro MyContinueThread(thread)
  thread\cmd = #thread_cmd_continue
  If thread\signal
    SignalSemaphore(thread\signal)
  EndIf
EndMacro

Macro MyStopThread(thread)
  thread\cmd = #thread_cmd_stop
  If thread\signal
    SignalSemaphore(thread\signal)
  EndIf
EndMacro

; ***************************************************************************************

Procedure MyThread(*this.udtMyThread)
  
  Debug "Created Thread"
  
  With *this
    \signal = CreateSemaphore(1)
    
    Repeat
      Select \cmd 
        Case #thread_cmd_start
          \cmd = #thread_cmd_nothing
          If \state <= #thread_state_nothing Or \state >= #thread_state_finished
            \state = #thread_state_startingup
            SendThreadState(*this, \state)
            ;TODO Init thread
            Debug "Init Thread"
            Delay(2000)
            
            \state = #thread_state_running
            SendThreadState(*this, \state)
            
          EndIf
          
        Case #thread_cmd_pause
          \cmd = #thread_cmd_nothing
          If \state = #thread_state_running
            \state = #thread_state_pausing
            SendThreadState(*this, \state)
            ;TODO Pausing thread
            Debug "Paused Thread"
            Delay(2000)
            
            \state = #thread_state_paused
            SendThreadState(*this, \state)
            
          EndIf
          
        Case #thread_cmd_continue
          \cmd = #thread_cmd_nothing
          If \state = #thread_state_paused
            \state = #thread_state_continued
            SendThreadState(*this, \state)
            ;TODO Continue thread
            Debug "Continue Thread"
            Delay(2000)
            
            \state = #thread_state_running
            SendThreadState(*this, \state)
            
          EndIf
          
        Case #thread_cmd_stop
          \cmd = #thread_cmd_nothing
          If \state < #thread_state_stopping
            \state = #thread_state_stopping
            SendThreadState(*this, \state)
            ;TODO Stopping thread
            Debug "Stopping Thread"
            Delay(2000)
            
            \state = #thread_state_stopped
            SendThreadState(*this, \state)
            
          EndIf
          
      EndSelect
      
      Select \state
        Case #thread_state_running
          ;TODO Cycle programm
          Debug "Thread running " + \counter
          
          \counter + 1
          Delay(1000)
          
        Case #thread_state_nothing, #thread_state_paused   
          WaitSemaphore(\signal)
          
        Default
          Delay(100)
          
      EndSelect
      
    Until \state = #thread_state_stopped
    
    Debug "Release Thread"
    
    \state = #thread_state_finished
    SendThreadState(*this, \state)
    
    ; Release thread
    FreeSemaphore(\signal)
    \signal = 0
    \id = 0
  EndWith
  
EndProcedure

; ***************************************************************************************

CompilerIf #PB_Compiler_IsMainFile
  
  Global thread1.udtMyThread
  
  Procedure Main()
    
    If OpenWindow(0, #PB_Any, #PB_Any, 530, 60, "Simple Thread Control")
      CreateStatusBar(0, WindowID(0))
      AddStatusBarField(1000)
      ButtonGadget(0, 10, 10, 120, 25, "Start")
      ButtonGadget(1, 140, 10, 120, 25, "Pause")
      ButtonGadget(2, 270, 10, 120, 25, "Continue")
      ButtonGadget(3, 400, 10, 120, 25, "Stop")
      
      BindEvent(#thread_event_state, @ThreadState())
      
      ; We can create thread without start processing
      thread1\id = CreateThread(@MyThread(), @thread1)
      
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_Gadget  
            Select EventGadget()
              Case 0
                MyStartThread(thread1)
                
              Case 1
                MyPauseThread(thread1)
                
              Case 2
                MyContinueThread(thread1)
                
              Case 3
                MyStopThread(thread1)
                
            EndSelect
            
          Case #PB_Event_CloseWindow
            Break
            
        EndSelect
        
      ForEver
      
    EndIf
    
  EndProcedure : Main()
  
  
CompilerEndIf
Last edited by mk-soft on Fri Sep 02, 2016 3:57 pm, edited 5 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Simple Thread Control

Post by Kwai chang caine »

Code very usefull, for understanding the thread
Works great, thanks a lot for sharing 8)
ImageThe happiness is a road...
Not a destination
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Simple Thread Control

Post by davido »

@mk-soft,
Nice, instructive, example.
Thank you for sharing. :D
DE AA EB
User avatar
mk-soft
Always Here
Always Here
Posts: 6240
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Simple Thread Control

Post by mk-soft »

Update v1.03
- Update example with Semaphore

Have just a little much time, and I expanded the example with use of semaphore :wink:
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
aaaaaaaargh
User
User
Posts: 55
Joined: Thu Jul 27, 2006 1:24 pm

Re: Simple Thread Control

Post by aaaaaaaargh »

Thanks for sharing!
Post Reply