[SOLVED] Progress bars, events, macOS - howto?

Just starting out? Need help? Post your questions and find answers here.
User avatar
SparrowhawkMMU
User
User
Posts: 56
Joined: Fri Jan 17, 2014 8:55 pm
Location: UK

[SOLVED] Progress bars, events, macOS - howto?

Post by SparrowhawkMMU »

Hi,

PB 6.21
macOS 15.6.1 (although ideally I'd love for this to work on Win and Linux too at some stage)

I know that this has been discussed before, but to be honest I did not understand the solutions and some don't work on macOS anyway (ie simulating a DoEvents with an embedded mini WaitWindowEvent() loop)

I am trying to get a progress bar to update on each iteration of a time-consuming operation (decompress tar file, extract JSON file, read file, parse file, check if file components are in db, if not, add to db, if yes, update any changes)

Everything works except the progress bar. I have read on numerous posts here that I need to use threads for this, but I can't figure out how, and was wondering whether anyone could help out.

I have created a simple PB script to try to work out how this should work (see below), but it does not work.

It uses a global var to hold the current value of the progress bar state, which the thread is supposed to pick up and then update the status bar.

I've also tried creating a custom event that sets the gadget state which is raised by PostEvent() each time the loop increments, but that did not work either.

I've tried with the gadget click event in the main event loop and also using BindGadget().

The compiler has Create Threadsafe Executable set to ON. (ticked)

Am I anywhere close, or am I way off?
I'd really appreciate any help on this as the rest of the application all works and this is the finishing touch that would make it just that little bit a nicer user experience.

Thanks :)

Code: Select all

EnableExplicit

Enumeration 0
  #CONTROL_ProgressBar
  #CONTROL_StartButton
EndEnumeration

Global g_updateThreadId.i = 0
Global g_progress.i = 0

Declare StartClicked()
Declare UpdateProgressBar(*value)

OpenWindow(0, 0, 0,400, 200, "Progress Bar Test", #PB_Window_ScreenCentered)

ProgressBarGadget(#CONTROL_ProgressBar, 20, 50, 360, 10, 0, 100)
ButtonGadget(#CONTROL_StartButton, 280, 70, 100, 25, "Start B")

; BindGadgetEvent(#CONTROL_StartButton, @StartClicked())

g_updateThreadId = CreateThread(@UpdateProgressBar(), 0)
If IsThread(g_updateThreadId)
  Debug "Thread ID: " + Str(g_updateThreadId)
Else
  Debug "Could not create thread"
EndIf

Define eventNumber.i = 0	  
Repeat
  eventNumber = WaitWindowEvent()	
 
  Select eventNumber
    Case #PB_Event_Menu
      Select EventMenu()
        Case -4 ; Quit
          Break      
      EndSelect
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #CONTROL_StartButton : StartClicked()
      EndSelect
  EndSelect
Until eventNumber = #PB_Event_CloseWindow

End

Procedure UpdateProgressBar(*value)
  Debug ">>> UpdateProgressBar()"
  Repeat 
    SetGadgetState(#CONTROL_ProgressBar, g_progress)
  ForEver
EndProcedure

Procedure StartClicked()
  Debug ">>> StartClicked()"
  
  Protected i.i  
    
  For i = 0 To 100    
    g_progress = i        
    Delay(10) ; my time-consuming logic here
    Debug Str(i)
  Next i  
  
EndProcedure

Last edited by SparrowhawkMMU on Tue Sep 02, 2025 5:12 pm, edited 1 time in total.
infratec
Always Here
Always Here
Posts: 7613
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Progress bars, events, macOS - howto?

Post by infratec »

You did it the wrong way:
not the update needs to be inside of a thread, your thread needs to be the slow part.
Then the slow part can update the bar via PostEvent.

Code: Select all

CompilerIf Not #PB_Compiler_Thread
  CompilerError "You need to enable thread safe in compiler settings"
CompilerEndIf

EnableExplicit

Enumeration
  #CONTROL_ProgressBar
EndEnumeration

Enumeration #PB_Event_FirstCustomValue
  #CustomEvent_UpdateProgressBar
EndEnumeration


Procedure DoSomethingLong(*Exit.Integer)
  
  Protected i.i
  
  For i = 100 To 0 Step -1
    PostEvent(#CustomEvent_UpdateProgressBar, 0, 0, 0, i)
    Delay(1000)
    If *Exit\i
      Break
    EndIf
  Next i
  
EndProcedure



Define.i ThreadID, eventNumber, ThreadExit

OpenWindow(0, 0, 0,400, 200, "Progress Bar Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

ProgressBarGadget(#CONTROL_ProgressBar, 20, 50, 360, 10, 0, 100)

ThreadId = CreateThread(@DoSomethingLong(), @ThreadExit)

Repeat
  eventNumber = WaitWindowEvent()	
 
  Select eventNumber
    Case #CustomEvent_UpdateProgressBar
      SetGadgetState(#CONTROL_ProgressBar, EventData())
    
  EndSelect
Until eventNumber = #PB_Event_CloseWindow

If IsThread(ThreadID)
  ThreadExit = #True
  If WaitThread(ThreadID, 2000) = 0
    Debug "Should never happen"
    KillThread(ThreadID)
  EndIf
EndIf
User avatar
SparrowhawkMMU
User
User
Posts: 56
Joined: Fri Jan 17, 2014 8:55 pm
Location: UK

Re: Progress bars, events, macOS - howto?

Post by SparrowhawkMMU »

Thank you so much infratec! That makes much more sense, thank you :)
Post Reply