Page 1 of 1
Gui menu select blocks thread ?
Posted: Sat Dec 23, 2017 4:13 pm
by Martt
Code: Select all
EnableExplicit
Global Semaphore.i
Declare Main()
Declare Thread(*Dummy)
Enumeration #PB_Event_FirstCustomValue
#Thread_Finished
#Thread_AddText
EndEnumeration
Enumeration
#MAIN_WINDOW
#EDITOR_WINDOW
#MENU
#FILE_RUN
#FILE_QUIT
EndEnumeration
Procedure Main()
Protected Exit.b
Protected Event.i
Protected Thread.i
#Width = 400
#Height = 400
#Space = 10
OpenWindow(#MAIN_WINDOW, 100, 100, #Width, #Height, "Main Window")
EditorGadget(#EDITOR_WINDOW, #Space, #Space, #Width - (#Space * 2), #Height - MenuHeight() - (#Space * 2), #PB_Editor_ReadOnly)
CreateMenu(#MENU, WindowID(#MAIN_WINDOW))
MenuTitle("File")
MenuItem(#FILE_RUN, "Run")
MenuItem(#FILE_QUIT, "Quit")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Exit = #True
Case #Thread_AddText
AddGadgetItem(#EDITOR_WINDOW, -1, PeekS(EventData()))
; Goto last character (auto scroll)
SendMessage_(GadgetID(#EDITOR_WINDOW), #EM_SETSEL, -1, -1)
SignalSemaphore(Semaphore)
Case #Thread_Finished
DisableMenuItem(#MENU, #FILE_RUN, #False)
SignalSemaphore(Semaphore)
Case #PB_Event_Menu
Event = EventMenu()
Select Event
Case #FILE_RUN
DisableMenuItem(#MENU, #FILE_RUN, #True)
Thread = CreateThread(@Thread(), #Null)
Case #FILE_QUIT
Exit = #True
EndSelect
EndSelect
Until Exit
; Kill thread if needed...
If IsThread(Thread) : KillThread(Thread) : EndIf
FreeMenu(#MENU)
CloseWindow(#MAIN_WINDOW)
EndProcedure
Procedure Thread(*Dummy)
Protected LoopCnt.i
Protected Output.s
For LoopCnt = 1 To 10000
Output = "This string is number " + Str(LoopCnt)
; Send output to gui and wait for gui to process...
Semaphore = CreateSemaphore()
PostEvent(#Thread_AddText, #Null, #Null, #Null, @Output)
WaitSemaphore(Semaphore)
FreeSemaphore(Semaphore)
Next
; Done, let the gui know were done...
Semaphore = CreateSemaphore()
PostEvent(#Thread_Finished, #Null, #Null, #Null, #Null)
WaitSemaphore(Semaphore)
FreeSemaphore(Semaphore)
EndProcedure
Main()
End
Newbie question here. In this test program, the menuoption File->Run will run the
thread. But if the
thread is running and I click on File, the
thread stops displaying output. Likely because of the Semaphore.
Is there a way around it besides HideMenu(), which messes up the coordinates of the editorgadget ?
Re: Gui menu select blocks thread ?
Posted: Sat Dec 23, 2017 4:54 pm
by infratec
Hi,
the
thread is still running, but paused by waiting on the semaphore.
The main eventloop is stooped by your menu access, so it can not process the Events.
You can avoid this by using BindEvent()
Code: Select all
EnableExplicit
Structure ThreadParameterStructure
Thread.i
Semaphore.i
Exit.i
EndStructure
Declare Main()
Declare Thread(*Dummy)
Enumeration #PB_Event_FirstCustomValue
#Thread_Finished
#Thread_AddText
EndEnumeration
Enumeration
#MAIN_WINDOW
#EDITOR_WINDOW
#MENU
#FILE_RUN
#FILE_QUIT
EndEnumeration
Global ThreadParameter.ThreadParameterStructure
Procedure Test()
AddGadgetItem(#EDITOR_WINDOW, -1, PeekS(EventData()))
SendMessage_(GadgetID(#EDITOR_WINDOW), #EM_SETSEL, -1, -1)
SignalSemaphore(ThreadParameter\Semaphore)
EndProcedure
Procedure Main()
Protected Exit.b
Protected Event.i
Protected Thread.i
;Protected ThreadParameter.ThreadParameterStructure
#Width = 400
#Height = 400
#Space = 10
OpenWindow(#MAIN_WINDOW, 100, 100, #Width, #Height, "Main Window")
EditorGadget(#EDITOR_WINDOW, #Space, #Space, #Width - (#Space * 2), #Height - MenuHeight() - (#Space * 2), #PB_Editor_ReadOnly)
CreateMenu(#MENU, WindowID(#MAIN_WINDOW))
MenuTitle("File")
MenuItem(#FILE_RUN, "Run")
MenuItem(#FILE_QUIT, "Quit")
ThreadParameter\Semaphore = CreateSemaphore()
BindEvent(#Thread_AddText, @Test())
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Exit = #True
; Case #Thread_AddText
; AddGadgetItem(#EDITOR_WINDOW, -1, PeekS(EventData()))
; ; Goto last character (auto scroll)
; SendMessage_(GadgetID(#EDITOR_WINDOW), #EM_SETSEL, -1, -1)
; SignalSemaphore(ThreadParameter\Semaphore)
Case #Thread_Finished
DisableMenuItem(#MENU, #FILE_RUN, #False)
Case #PB_Event_Menu
Event = EventMenu()
Select Event
Case #FILE_RUN
DisableMenuItem(#MENU, #FILE_RUN, #True)
ThreadParameter\Thread = CreateThread(@Thread(), @ThreadParameter)
Case #FILE_QUIT
Exit = #True
EndSelect
EndSelect
Until Exit
; Kill thread if needed...
If IsThread(Thread)
ThreadParameter\Exit = #True
If WaitThread(ThreadParameter\Thread, 1000) = 0
KillThread(ThreadParameter\Thread)
EndIf
EndIf
FreeSemaphore(ThreadParameter\Semaphore)
FreeMenu(#MENU)
CloseWindow(#MAIN_WINDOW)
EndProcedure
Procedure Thread(*Parameter.ThreadParameterStructure)
Protected LoopCnt.i
Protected Output.s
For LoopCnt = 1 To 10000
Output = "This string is number " + Str(LoopCnt)
; Send output to gui and wait for gui to process...
PostEvent(#Thread_AddText, #Null, #Null, #Null, @Output)
WaitSemaphore(*Parameter\Semaphore)
Next
PostEvent(#Thread_Finished, #Null, #Null, #Null, #Null)
EndProcedure
Main()
I also eliminated your CreateSemaphore() marathon
Bernd
Re: Gui menu select blocks thread ?
Posted: Sat Dec 23, 2017 5:10 pm
by srod
Yes Windows will enter a modal event loop when a menu is opened which will block the main process's message retrieval. Your
thread still runs, but it is of course waiting for your semaphore to be signaled which won't happen until Window's releases the message queue etc.
You can make the menu modeless with the #MNS_MODELESS flag, but you'll need to do this through API and you'll end up with a menu which won't behave the way your user's expect!
**EDIT : now I didn't think of using BindEvent()!

Nice one.
Re: Gui menu select blocks thread ?
Posted: Sat Dec 23, 2017 6:11 pm
by skywalk
Nice

I did not expect BindEvent() to update the gui while the user interacts with the gui?
So, BindEvent()'s can access GUI elements, while our threads cannot.
Re: Gui menu select blocks thread ?
Posted: Sat Dec 23, 2017 6:14 pm
by srod
The event procedures are still being called in the context of the main process so there is no problem there. The menu modal loop will ensure that all controls still receive their paint events (else the controls will appear to freeze whilst a menu is displayed) and it is invariably here that our bound event procedures are being called.
Re: Gui menu select blocks thread ?
Posted: Sat Dec 23, 2017 6:38 pm
by skywalk
Yes, dropping bindevent() and applying the gui update in the main event loop, causes the original complaint of locking the thread. bindevent() is updating in parallel with the main event loop. Our threads do not have the same luxury.
Re: Gui menu select blocks thread ?
Posted: Sun Dec 24, 2017 6:39 am
by Martt
infratec wrote:Hi,
the
thread is still running, but paused by waiting on the semaphore.
The main eventloop is stooped by your menu access, so it can not process the Events.
You can avoid this by using BindEvent()
I also eliminated your CreateSemaphore() marathon
Bernd
Thanks for the BindEvent. I did not expect Windows to stop the eventloop on a single menu click

.
And the CreateSemaphore marathon, yeah.... Kind of dumb.
Thanks for the answer. Now the project can continue....
Re: Gui menu select blocks thread ?
Posted: Sun Dec 24, 2017 12:23 pm
by mk-soft
For easy work between threads and GUI i have wrote a module. Perhaps help this...
Link:
Module ThreadToGUI
Re: Gui menu select blocks thread ?
Posted: Sun Dec 24, 2017 7:05 pm
by skywalk
Thanks mk-soft and infratec for pointing out the BindEvent() behavior with threads.
