How to refresh?
How to refresh?
Hi all,
I log messages to a listview gadget via AddItem(). When a time-consuming command immediately follows my log command (such as deleting a large dir tree via DeleteDirectory), the message(s) show up in the listview AFTER the time-consuming command finishes.
How do I get them to show up immediately BEFORE the time-consuming command runs?
Thanks for any suggestions!
I log messages to a listview gadget via AddItem(). When a time-consuming command immediately follows my log command (such as deleting a large dir tree via DeleteDirectory), the message(s) show up in the listview AFTER the time-consuming command finishes.
How do I get them to show up immediately BEFORE the time-consuming command runs?
Thanks for any suggestions!
Re: How to refresh?
you must handle the windows-events
will do it, BUT it ignores all events!
Code: Select all
while windowevent():wend
Re: How to refresh?
Oops, forgot to mention that my code runs in a callback proc (after a button click) so I cannot call WaitEvent/WaitWindowEvent in there ...
Re: How to refresh?
For long running code you need a thread.
Re: How to refresh?
It will be very helpful if you posted a very simple exam.to show how you run your commands with windows callback
Egypt my love
Re: How to refresh?
Like so:
Code: Select all
EnableExplicit
Enumeration Gadgets
#CurWindow
#ButtonStart
#ListviewLog
EndEnumeration
#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601
Procedure LogMessage(Msg.s)
AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + Msg)
EndProcedure
Procedure ButtonClick()
ClearGadgetItems(#ListviewLog)
LogMessage("Process started.")
; now start a time consuming process here (in my case, deleting a huge dir tree)
; the log message only shows up upon completion of that process
EndProcedure
Procedure OpenFormWindow()
If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(#ButtonStart, 10, 10, 80, 25, "Start")
ListViewGadget(#ListviewLog, 10, 40, 780, 550)
BindGadgetEvent(#ButtonStart, @ButtonClick())
EndIf
EndProcedure
OpenFormWindow()
Define Event
Repeat
Event = WaitWindowEvent()
Select Event
; ...
EndSelect
Until Event = #PB_Event_CloseWindow
Re: How to refresh?
Example of a thread that updates the main interface (yes, you can, as long as the updated gadget is not accessed at the same time by another part of the program).
With this system, the interface is not blocked during the Deltree
But you can't show the state of DeleteDirectory() because it's au single command.
You can "pass the time" by making a fake progressbar (i.e update sec by sec)
Check [X] ThreadSafe in compiler option.
With this system, the interface is not blocked during the Deltree
Code: Select all
EnableExplicit
Enumeration Gadgets
#CurWindow
#ButtonStart
#ListviewLog
EndEnumeration
#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601
Procedure LogMessage(Msg.s)
AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + Msg)
EndProcedure
; --- main task running in thread
Procedure DeleteTree(*value)
Protected i
Repeat
i + 1
; --- Yes, you can update main GUI if no other task modify the gadget
LogMessage("Hi " + Str(i))
Delay(1000)
ForEver
EndProcedure
Procedure ButtonClick()
ClearGadgetItems(#ListviewLog)
LogMessage("Process started.")
; now start a time consuming process here (in my case, deleting a huge dir tree)
; the log message only shows up upon completion of that process
; Main task
CreateThread(@DeleteTree(), 1)
EndProcedure
Procedure OpenFormWindow()
If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(#ButtonStart, 10, 10, 80, 25, "Start")
ListViewGadget(#ListviewLog, 10, 40, 780, 550)
BindGadgetEvent(#ButtonStart, @ButtonClick())
EndIf
EndProcedure
OpenFormWindow()
Define Event
Repeat
Event = WaitWindowEvent()
Select Event
; ...
EndSelect
Until Event = #PB_Event_CloseWindow
You can "pass the time" by making a fake progressbar (i.e update sec by sec)
Check [X] ThreadSafe in compiler option.
Re: How to refresh?
IMPORTANT. You should not call Gadget/Windows-Commands in Threads. It works on Windows, but not on other os.
Re: How to refresh?
Tested on Linux Slackware with PB 5.73 LTS x64: Work fine
I don't have a mac, but knowing that they are based on *BSD it must also work, I think.
Maybe it was valid for the old versions of PB?
So far I never had any problem, but all my programs are still very "basic": I almost never use pointers for example and very rarely direct API calls
Re: How to refresh?
On Linux work perhaps, but not stable ...
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
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: How to refresh?
@Marcus:
Hmm - not so sure about your solution. As it stands, it works flawlessly or so it seems. The moment I add a WaitThread(), it hangs.
However, if I remove the GUI calls it works with WaitThread().
Hmm - not so sure about your solution. As it stands, it works flawlessly or so it seems. The moment I add a WaitThread(), it hangs.
However, if I remove the GUI calls it works with WaitThread().
Re: How to refresh?
Solution with PostEvent ... Not the first
Update
- macOS don't like running thread ...
Update
- macOS don't like running thread ...
Code: Select all
EnableExplicit
Procedure AllocateString(Text.s)
Protected *mem.String
*mem = AllocateStructure(String)
If *mem
*mem\s = Text
EndIf
ProcedureReturn *mem
EndProcedure
Procedure.s FreeString(*Mem.String)
Protected r1.s
If *Mem
r1 = *Mem\s
FreeStructure(*Mem)
EndIf
ProcedureReturn r1
EndProcedure
; ----
Enumeration Gadgets
#CurWindow
#ButtonStart
#ListviewLog
EndEnumeration
#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601
Enumeration CustomEvent #PB_Event_FirstCustomValue
#MyEvent_LogMessage
EndEnumeration
Procedure DispatchLogMessage()
AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + FreeString(EventData()))
EndProcedure
BindEvent(#MyEvent_LogMessage, @DispatchLogMessage())
Procedure LogMessage(Msg.s)
PostEvent(#MyEvent_LogMessage, 0, 0, 0, AllocateString(Msg))
EndProcedure
Global ExitThreads
; --- main task running in thread
Procedure DeleteTree(*value)
Protected i
Repeat
i + 1
; --- Yes, you can update main GUI if no other task modify the gadget
LogMessage("Hi " + Str(i))
Delay(1000)
Until ExitThreads
EndProcedure
Procedure ButtonClick()
ClearGadgetItems(#ListviewLog)
LogMessage("Process started.")
; now start a time consuming process here (in my case, deleting a huge dir tree)
; the log message only shows up upon completion of that process
; Main task
CreateThread(@DeleteTree(), 1)
EndProcedure
Procedure OpenFormWindow()
If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(#ButtonStart, 10, 10, 80, 25, "Start")
ListViewGadget(#ListviewLog, 10, 40, 780, 550)
BindGadgetEvent(#ButtonStart, @ButtonClick())
EndIf
EndProcedure
OpenFormWindow()
Define Event
Repeat
Event = WaitWindowEvent()
Select Event
; ...
EndSelect
Until Event = #PB_Event_CloseWindow
ExitThreads = #True
Delay(2000)
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
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: How to refresh?
Hi
Did not test it but I hope it will do the job
Did not test it but I hope it will do the job
Code: Select all
EnableExplicit
Global start,startflag
Enumeration Gadgets
#CurWindow
#ButtonStart
#ListviewLog
EndEnumeration
#DateTimeFormat = "%yyyy-%mm-%dd %hh:%ii:%ss" ; ISO 8601
Procedure LogMessage(Msg.s)
AddGadgetItem(#ListviewLog, -1, FormatDate(#DateTimeFormat, Date()) + " " + Msg)
EndProcedure
Procedure ButtonClick()
ClearGadgetItems(#ListviewLog)
LogMessage("Process started.")
startflag = 1
start = ElapsedMilliseconds()
; now start a time consuming process here (in my case, deleting a huge dir tree)
; the log message only shows up upon completion of that process
startflag = 0
EndProcedure
Procedure OpenFormWindow()
If OpenWindow(#CurWindow, #PB_Ignore, #PB_Ignore, 800, 600, "Issue Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(#ButtonStart, 10, 10, 80, 25, "Start")
ListViewGadget(#ListviewLog, 10, 40, 780, 550)
BindGadgetEvent(#ButtonStart, @ButtonClick())
AddWindowTimer(#CurWindow,125,10)
EndIf
EndProcedure
OpenFormWindow()
Define Event
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit =1
Case #PB_Event_Timer
If startflag = 1
LogMessage(Str(ElapsedMilliseconds()-start) +" % Completed")
EndIf
; ...
EndSelect
Until Quit = 1
Egypt my love
Re: How to refresh?
As indicated in the help, WaitThread() completely STOPS the main part of the program (partly like Delay, which STOPS ALL the program). Avoid use this technic
To get information from a thread, use rather Rashad's solution (Flag) or mksoft's (PostEvent)
To get information from a thread, use rather Rashad's solution (Flag) or mksoft's (PostEvent)
Re: How to refresh?
Thank you all for your contributions - much appreciated.