Page 1 of 2
[Implemented] #WM_USER - Private Messages in WindowEvent
Posted: Sun Sep 04, 2005 2:27 pm
by nco2k
Implemented as PostEvent()
hi folks,
how to find out when a thread has finished??
possible solution could look like:
Code: Select all
#Title = "Thread-Test"
Procedure Thread()
;do stuff...
MessageRequester(#Title, "a hello from our Thread")
;end thread...
SendMessage_(WindowID(0), #WM_USER+1, 0, 0)
EndProcedure
If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title)
If CreateThread(@Thread(), 0)
Repeat
WinEvent.l = WaitWindowEvent()
Select WinEvent
Case #WM_USER+1 ;<--- but won't work
ThreadEnd = #True
Break
Case #PB_Event_CloseWindow
WindowEnd = #True
Break
EndSelect
ForEver
If WindowEnd = #False And ThreadEnd = #True
MessageRequester(#Title, "App was closed AFTER the Thread has finished")
Else
MessageRequester(#Title, "App was closed BEFORE the Thread could finished")
EndIf
EndIf
EndIf
End
but that won't work...
so how to leave the WaitWindowEvent() loop, if you can't / don't want to use WindowEvent() instead ??
i did this by a trick for now:
Code: Select all
#Title = "Thread-Test"
Global ThreadEnd.l
Procedure Thread()
;do stuff...
MessageRequester(#Title, "a hello from our Thread")
;end thread...
ThreadEnd = #True
ResizeWindow(WindowWidth() + 1, WindowHeight() + 1)
EndProcedure
If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title)
If CreateThread(@Thread(), 0)
Repeat
WinEvent.l = WaitWindowEvent()
If WinEvent = #PB_Event_SizeWindow
If ThreadEnd = #True
Break
EndIf
ElseIf WinEvent = #PB_Event_CloseWindow
WindowEnd = #True
Break
EndIf
ForEver
If WindowEnd = #False And ThreadEnd = #True
MessageRequester(#Title, "App was closed AFTER the Thread has finished")
Else
MessageRequester(#Title, "App was closed BEFORE the Thread could finished")
EndIf
EndIf
EndIf
End
but stil, i think it would be nice if we could check #WM_USER messages in WindowEvent if possible?! i mean #WM_LBUTTONDOWN etc. also work in WindowEvent.
and btw a IsThread() would be very very very... usefull

for something like Repeat : Until IsThread() = #False.
//EDIT:
hmm... or how about a own simple but very usefull and cross platform compatible, pb intern message system??
something like:
Code: Select all
SendPBMessage(99) ;send a value of 99
WinEvent.l = WaitWindowEvent()
Select WinEvent
Case #PB_Event_Message
If GetPBMessage() = 99 ;return the value of 99
MessageRequester("PB-Message", "dance in the rain!")
Else
MessageRequester("PB-Message", "drink beer!")
EndIf
EndSelect
and it also should/could work without a window, cause of the GetPBMessage() command... just think of the possibilities.
c ya,
nco2k
Posted: Mon Sep 05, 2005 11:02 am
by gnozal
You can get the (#WM_USER+1) event in the callback.
Code: Select all
#Title = "Thread-Test"
Global ThreadEnd
Procedure Thread()
;do stuff...
MessageRequester(#Title, "a hello from our Thread")
;end thread...
SendMessage_(WindowID(0), #WM_USER+1, 0, 0)
EndProcedure
Procedure callback(WindowID, message, wParam, lParam)
Result = #PB_ProcessPureBasicEvents
;
If message = #WM_USER+1
ThreadEnd = #True
EndIf
;
ProcedureReturn Result
EndProcedure
If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title)
SetWindowCallback(@callback())
If CreateThread(@Thread(), 0)
Repeat
WinEvent.l = WaitWindowEvent()
If ThreadEnd = #True
Break
EndIf
Select WinEvent
Case #PB_Event_CloseWindow
WindowEnd = #True
Break
EndSelect
ForEver
If WindowEnd = #False And ThreadEnd = #True
MessageRequester(#Title, "App was closed AFTER the Thread has finished")
Else
MessageRequester(#Title, "App was closed BEFORE the Thread could finished")
EndIf
EndIf
EndIf
End
But it's easier to directly set ThreadEnd = #True at the end of the thread.
Code: Select all
#Title = "Thread-Test"
Global ThreadEnd
Procedure Thread()
;do stuff...
MessageRequester(#Title, "a hello from our Thread")
;end thread...
ThreadEnd = #True
EndProcedure
If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title)
If CreateThread(@Thread(), 0)
Repeat
WinEvent.l = WaitWindowEvent()
If ThreadEnd = #True
Break
EndIf
Select WinEvent
Case #PB_Event_CloseWindow
WindowEnd = #True
Break
EndSelect
ForEver
If WindowEnd = #False And ThreadEnd = #True
MessageRequester(#Title, "App was closed AFTER the Thread has finished")
Else
MessageRequester(#Title, "App was closed BEFORE the Thread could finished")
EndIf
EndIf
EndIf
End
Posted: Mon Sep 05, 2005 11:11 am
by freak
With SendMessage_(), the message only arrives in the callback. To get the
message in the main loop, you must use PostMessage_() instead.
Posted: Mon Sep 05, 2005 11:13 am
by nco2k
@gnozal
erm... did you acctually read what i said?!
this IS the problem... a window event is needed, to check the ThreadEnd variable, so a callback or your other code is useless without a window event.
if you dont move your mouse over your window, or an other event doesnt appear, nothing will happen until then... :roll: maybe its a bad example code because after closing a MessageRequester() the window becomes active and returns a event.
//EDIT:
@freak
you are right, this is great! and i just thought the only difference between SendMessage_() and PostMessage_() is that PostMessage_() doesnt wait for the message to proceed.
c ya,
nco2k
Re: #WM_USER - Private Messages in WindowEvent
Posted: Mon Sep 05, 2005 12:01 pm
by PB
> how to find out when a thread has finished?
Use a global variable? For example: the app below won't let you close the window
until the thread has finished:
Code: Select all
Global MyThread
Procedure Thread()
Delay(Random(4000)+1000) ; Delay for 1-5 seconds.
MyThread=1
EndProcedure
If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
If CreateThread(@Thread(), 0)
Repeat : Until WaitWindowEvent()=#PB_EventCloseWindow And MyThread=1
EndIf
EndIf
Posted: Mon Sep 05, 2005 12:11 pm
by nco2k
@PB
Use a global variable?
i tried this already.
the app below won't let you close the window
until the thread has finished
and until a window event returns. and that was the problem.
i dont want to close the window. i just wanted, to modify it after the thread has finished, without the need of an user to "force" a window event... but the tip with PostMessage_() works great.
p.s.: without a window event, you can wait for hours.
Code: Select all
Global MyThread
Procedure Thread()
Delay(Random(4000)+1000) ; Delay for 1-5 seconds.
MyThread=1
EndProcedure
If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
If CreateThread(@Thread(), 0)
Repeat : If MyThread=1 : Break : EndIf : Until WaitWindowEvent()=#PB_EventCloseWindow
EndIf
EndIf
c ya,
nco2k
Posted: Mon Sep 05, 2005 12:40 pm
by PB
> i dont want to close the window
That was just an example to show that the app was waiting until the thread
was finished -- just like you asked.
> If MyThread=1 : Break : EndIf
What point are you making here? Of course this lets you close the window,
because MyThread won't be 1 until the delay has passed. I still fail to see
what the problem is. You asked "how to find out when a thread has finished"
and I showed you. Maybe you can show me some code that is causing you
a problem? It all seems cut-and-dry to me...
> this IS the problem... a window event is needed, to check the ThreadEnd variable
Huh? No window event is needed, observe:
Code: Select all
Global ThreadEnd
Procedure Thread()
Delay(3000)
ThreadEnd=1
EndProcedure
CreateThread(@Thread(),0)
Debug "Wait for thread to end after 3 seconds..."
Repeat : Delay(1) : Until ThreadEnd=1
Debug "Thread ended!"
Posted: Mon Sep 05, 2005 12:57 pm
by Dare2
So, it depends on how the loop is handled, right? Or wrong?
With waitWindowEvent() you just keep waiting until something happens to trigger an event. But the other apps love you because you're no hog.
With WindowEvent() you get to check the flag each pass through but you are less friendly to the other apps, even with delay?
With callback you get a friendly prod? ( I love callbacks - everything should have a callback option

).
And the extra event mooted here would allow WaitWindowEvent good-neighbourliness along with the ability to check for the event you wanted?
What would be nice would be a way to inform the PureBasic controller which extra events to let through.
LetThisDogLoose(eventInfo). It could build a table and check ...

Posted: Mon Sep 05, 2005 1:01 pm
by nco2k
@PB
What point are you making here?
that was an example that nothing will happen, without a window event.
You don't need to "force" a window event or anything
of course you have to, because without a window event the code wont go on.
You asked "how to find out when a thread has finished"
and I showed you.
well you showed me how to find out when a thread is finished, but with the need of a window event to check the variable. i was just triyng to check if a thread has finished, without the need to move the window or something like that, to check the global variable and thats what i do now, with the PostMessage_(WindowID(0), #WM_USER+1, 0, 0) without problem. so i "force" a event with this command.
sure the easiest way would be WindowEvent() instead of WaitWindowEvent() but thats another story.
Huh? No window event is needed, observe:
this is so silly, cause there is no Window + WaitWindowEvent(). :roll:
c ya,
nco2k
Posted: Mon Sep 05, 2005 1:05 pm
by nco2k
@PB
yeah and thats a whole other world, cause there is no WaitWindowEvent() which "freeze" your app without a event... so you can go on with the variable checking without any probs... no big deal.
c ya,
nco2k
Posted: Mon Sep 05, 2005 1:08 pm
by PB
> you showed me how to find out when a thread is finished, but with the
> need of a window event to check the variable
Because that was just an example... you didn't specify how or when you
need the variable checked, so I did my example in the manner of the user
not being able to exit the app until the thread ends. Sheesh, I can't win!

Posted: Mon Sep 05, 2005 1:15 pm
by PB
> i was just triyng to check if a thread has finished, without the need to move
> the window or something like that, to check the global variable
This is what I don't understand... you don't NEED to move the window, or force
a window event, to check the value of the global variable. Can you show me
a situation where you need to -- where it WON'T work without it? Thanks.
Posted: Mon Sep 05, 2005 1:18 pm
by nco2k
@PB
yes of course, i didnt want to say your example is wrong or bad or something like that, only that its dependent to a window event.
ok deal... how would you break this loop after the thread has finished, without the need for a callback or a window event, only by just looking with your eyes.
Code: Select all
Procedure Thread()
Delay(Random(4000)+1000)
EndProcedure
If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
If CreateThread(@Thread(), 0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
MessageRequester("test", "test")
EndIf
EndIf
End
i showed you already a example where a window event is needed, dont forget moving your mouse causes events too.
Code: Select all
Global ThreadEnd.l
Procedure Thread()
Delay(Random(4000)+1000)
ThreadEnd = #True
EndProcedure
If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
If CreateThread(@Thread(), 0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
If ThreadEnd = #True
Break
EndIf
ForEver
MessageRequester("test", "test")
EndIf
EndIf
End
c ya,
nco2k
Posted: Mon Sep 05, 2005 1:32 pm
by PB
> how would you break this loop after the thread has finished
Your second example shows how... let it run and it breaks automatically when
the thread finishes -- just as I would have done -- and it doesn't use a window
event to do it (it just checks the global var alone and breaks accordingly).
I still fail to see any problem here. Maybe I just don't understand what you're
asking. It seems so simple and straightforward to me, that your questions are
starting to confuse me.

Posted: Mon Sep 05, 2005 1:38 pm
by nco2k
@PB
yes i think, you dont understand what i mean.
wait 15 seconds without causing any events... the MessageRequester() wont appear... only after a event happens.
Code: Select all
Global ThreadEnd.l
Procedure Thread()
Delay(Random(4000)+1000)
ThreadEnd = #True
EndProcedure
If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
If CreateThread(@Thread(), 0)
Repeat
WinEvent.l = WaitWindowEvent()
Debug "EVENT!!"
If ThreadEnd = #True
Break
EndIf
If WinEvent = #PB_Event_CloseWindow
End
EndIf
ForEver
MessageRequester("test", "test")
EndIf
EndIf
End
dont forget to put your cursor miles away of the window.
i dont say you need a event to
check a variable, i just say, you need a event that the programm goes on, so it can check the variable.
c ya,
nco2k