SetTimer
-
UINT_PTR timer = SetTimer(1 , 1000 , NULL); m_timeOut = FALSE; while(!m_rxBufferRecivied && !m_timeOut) { } KillTimer(timer); . . . void CMainFrame::OnTimer(UINT_PTR nIDEvent) { m_timeOut = TRUE; } In this code i wait in a while loop unil input buffer recieved. Before the loop i set a timer to wait maximum 1 second so the program wont stack in a loop(in case there is error receving buffer). If i remove the while loop timer callback function ONTimer works fine every second but with the loop the program stacks in a endless loop. What am i doing wrong? Thanks.
If you have a long running loop, chewing up cycles waiting for something to happen, to keep the GUI responsive (and to let things like timer events happen), you should periodically let Windows process messages. Stick this somewhere in your 'while' loop. At the top or bottom are the usual places.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}And it is true that keeping the GUI and application functions separate in a thread is a good idea, sometimes it's just too much work to re-do an application's logic to introduce threading when none existed before. In those cases, this should do the trick and not be too "architecturally impure".
-
UINT_PTR timer = SetTimer(1 , 1000 , NULL); m_timeOut = FALSE; while(!m_rxBufferRecivied && !m_timeOut) { } KillTimer(timer); . . . void CMainFrame::OnTimer(UINT_PTR nIDEvent) { m_timeOut = TRUE; } In this code i wait in a while loop unil input buffer recieved. Before the loop i set a timer to wait maximum 1 second so the program wont stack in a loop(in case there is error receving buffer). If i remove the while loop timer callback function ONTimer works fine every second but with the loop the program stacks in a endless loop. What am i doing wrong? Thanks.
In addition to the other replies.... There's rarely a need to sit in a loop on the UI/message-loop thread. Waiting on I/O should be done on separate thread(s). IMO, learn how to use threads and thread synchronization objects like events and your app will be much better behaved (not eating CPU cycles doing nothing). Even a PeekMessage loop is going to peg a virtual processor unnecessarily. At least use GetMessage() if you can :)
Mark Salsbery :java:
-
In addition to the other replies.... There's rarely a need to sit in a loop on the UI/message-loop thread. Waiting on I/O should be done on separate thread(s). IMO, learn how to use threads and thread synchronization objects like events and your app will be much better behaved (not eating CPU cycles doing nothing). Even a PeekMessage loop is going to peg a virtual processor unnecessarily. At least use GetMessage() if you can :)
Mark Salsbery :java:
Yes, PeekMessage() is CPU intensive but GetMessage() blocks. PeekMessage() allows your GUI to be "responsive" incase the user clicks on something, GetMessage() waits UNTIL the user clicks on something. (Yes, I know "Clicks or types or something")
-
Yes, PeekMessage() is CPU intensive but GetMessage() blocks. PeekMessage() allows your GUI to be "responsive" incase the user clicks on something, GetMessage() waits UNTIL the user clicks on something. (Yes, I know "Clicks or types or something")
Chuck O'Toole wrote:
PeekMessage() allows your GUI to be "responsive" incase the user clicks on something
All messages go through either function (unless filtered). If not there would be a ton of unresponsive apps that use getMessage() in their message loop(s) :)
Mark Salsbery :java:
-
Chuck O'Toole wrote:
PeekMessage() allows your GUI to be "responsive" incase the user clicks on something
All messages go through either function (unless filtered). If not there would be a ton of unresponsive apps that use getMessage() in their message loop(s) :)
Mark Salsbery :java:
You miss my point. If you have a loop like the OP that is doing something like polling for I/O then he's not getting back to the Windows message pump so his GUI is "unresponsive" (and his Timer requests aren't being handled - WM_TIMER). His problem is to *make* the GUI responsive while processing whatever he's doing. A "PeekMessage()" loop, strategically placed in his processing loop, will allow the Windows Messages to be processed. A "GetMessage()" loop, while it would make his GUI responsive, would totally hang *his* processing loop. So he needs a solution that keeps his loop running while allowing Windows to processes pending messages, hence "PeekMessage()". Yes, threads might serve him better but at the cost of redesigning his app. A PeekMessage() loop is a quickie solution to this particular problem.
-
In addition to the other replies.... There's rarely a need to sit in a loop on the UI/message-loop thread. Waiting on I/O should be done on separate thread(s). IMO, learn how to use threads and thread synchronization objects like events and your app will be much better behaved (not eating CPU cycles doing nothing). Even a PeekMessage loop is going to peg a virtual processor unnecessarily. At least use GetMessage() if you can :)
Mark Salsbery :java:
-
If you have a long running loop, chewing up cycles waiting for something to happen, to keep the GUI responsive (and to let things like timer events happen), you should periodically let Windows process messages. Stick this somewhere in your 'while' loop. At the top or bottom are the usual places.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}And it is true that keeping the GUI and application functions separate in a thread is a good idea, sometimes it's just too much work to re-do an application's logic to introduce threading when none existed before. In those cases, this should do the trick and not be too "architecturally impure".
No, dont do this, you are reinventing the wheel and possibly introducing instability. The message pump, which is what this is, is invisible in MFC apps (which I assume this guy is writing). Ansd in a C++ app having messages removed form the apps message queue and translated is at best ugly, and at worst dangerous, unless you KNOW that access to the apps message queue is multithread safe. The quick solution here is a sleep() call inside the loop. It is sidely used, and isnt going to cause any problems.
============================== Nothing to say.
-
Mark Salsbery wrote:
Waiting on I/O should be done on separate thread(s)
I agree, UI and IO should be kept apart. :)
============================== Nothing to say.
Thanks you all for the replies it was very usefull i learned alot!!!
-
No, dont do this, you are reinventing the wheel and possibly introducing instability. The message pump, which is what this is, is invisible in MFC apps (which I assume this guy is writing). Ansd in a C++ app having messages removed form the apps message queue and translated is at best ugly, and at worst dangerous, unless you KNOW that access to the apps message queue is multithread safe. The quick solution here is a sleep() call inside the loop. It is sidely used, and isnt going to cause any problems.
============================== Nothing to say.
Nonsense. Microsoft even documents this for dealing with exactly the kind of application. Occasionally, an application needs to examine the contents of a thread's message queue from outside the thread's message loop. For example, if an application's window procedure performs a lengthy drawing operation, you may want the user to be able to interrupt the operation. Unless your application periodically examines the message queue during the operation for mouse and keyboard messages, it will not respond to user input until after the operation has completed. Plus the user's loop is already preventing message processing, adding a Sleep() call will only *lengthen* the amount of time he's chewing up (real time, not cpu cycles obviously). This is well documented and long standing solution to *some* (not all) unresponsive GUI / Timer queue issues. Even threaded applications can do this, only not from multiple threads at the same time, obviously.
-
Nonsense. Microsoft even documents this for dealing with exactly the kind of application. Occasionally, an application needs to examine the contents of a thread's message queue from outside the thread's message loop. For example, if an application's window procedure performs a lengthy drawing operation, you may want the user to be able to interrupt the operation. Unless your application periodically examines the message queue during the operation for mouse and keyboard messages, it will not respond to user input until after the operation has completed. Plus the user's loop is already preventing message processing, adding a Sleep() call will only *lengthen* the amount of time he's chewing up (real time, not cpu cycles obviously). This is well documented and long standing solution to *some* (not all) unresponsive GUI / Timer queue issues. Even threaded applications can do this, only not from multiple threads at the same time, obviously.
Chuck O'Toole wrote:
Plus the user's loop is already preventing message processing, adding a Sleep() call will only *lengthen* the amount of time he's chewing up
No, quite the opposite. A sleep() surrenders the rest of that threads timeslice, it doesnt chew up cycles, it frees them. This function causes a thread to relinquish the remainder of its time slice [^] And if Microsoft recomends that then I am surprised. I can just imagine the code. DispatchMessage() is locked, because WM_DRAW hasnt come back from your message handler, so in that handler you call another DispatchMessage(). Perhaps you have some other handlers that are slow, so you do the same there. What a mess. Work intensive code should go in a seperate thread to the UI. Period, properly synchronised with the UI so the user has control.
Chuck O'Toole wrote:
not from multiple threads at the same time, obviously.
And why, because the PeekMessage()/TranslateMessage()/DispatchMessage() is not thread safe? :) Like I said, you risk instability.
============================== Nothing to say.
-
Chuck O'Toole wrote:
Plus the user's loop is already preventing message processing, adding a Sleep() call will only *lengthen* the amount of time he's chewing up
No, quite the opposite. A sleep() surrenders the rest of that threads timeslice, it doesnt chew up cycles, it frees them. This function causes a thread to relinquish the remainder of its time slice [^] And if Microsoft recomends that then I am surprised. I can just imagine the code. DispatchMessage() is locked, because WM_DRAW hasnt come back from your message handler, so in that handler you call another DispatchMessage(). Perhaps you have some other handlers that are slow, so you do the same there. What a mess. Work intensive code should go in a seperate thread to the UI. Period, properly synchronised with the UI so the user has control.
Chuck O'Toole wrote:
not from multiple threads at the same time, obviously.
And why, because the PeekMessage()/TranslateMessage()/DispatchMessage() is not thread safe? :) Like I said, you risk instability.
============================== Nothing to say.
Erudite__Eric wrote:
Chuck O'Toole wrote:
Plus the user's loop is already preventing message processing, adding a Sleep()
call will only *lengthen* the amount of time he's chewing upNo, quite the opposite. A sleep() surrenders the rest of that threads timeslice, it doesnt chew up cycles, it frees them.
And if Microsoft recomends that then I am surprised. Work intensive code should go in a seperate thread to the UI.If you're going to quote me, use the whole quote, not the part that makes it sound like the opposite of what I said. The actual quote should be:
Chuck O'Toole wrote:
Plus the user's loop is already preventing message processing, adding a Sleep() call will only *lengthen* the amount of time he's chewing up (real time, not cpu cycles obviously).
The parenthetical states that it's not the CPU Cycles but the "Clock On The Wall Cycles". Sleep() adds code to the loop, is a system call that adds more code being executed in the loop, and, even with Sleep(0) to quit the timeslice, still causes a complete scheduler cycle to look for other runnable threads before returning to this thread.
-
Erudite__Eric wrote:
Chuck O'Toole wrote:
Plus the user's loop is already preventing message processing, adding a Sleep()
call will only *lengthen* the amount of time he's chewing upNo, quite the opposite. A sleep() surrenders the rest of that threads timeslice, it doesnt chew up cycles, it frees them.
And if Microsoft recomends that then I am surprised. Work intensive code should go in a seperate thread to the UI.If you're going to quote me, use the whole quote, not the part that makes it sound like the opposite of what I said. The actual quote should be:
Chuck O'Toole wrote:
Plus the user's loop is already preventing message processing, adding a Sleep() call will only *lengthen* the amount of time he's chewing up (real time, not cpu cycles obviously).
The parenthetical states that it's not the CPU Cycles but the "Clock On The Wall Cycles". Sleep() adds code to the loop, is a system call that adds more code being executed in the loop, and, even with Sleep(0) to quit the timeslice, still causes a complete scheduler cycle to look for other runnable threads before returning to this thread.
Chuck O'Toole wrote:
Sleep() adds code to the loop,
Where as Peekmessage()/TranslateMessage()/DispatchMessage() does what? :)
Chuck O'Toole wrote:
even with Sleep(0) to quit the timeslice, still causes a complete scheduler cycle to look for other runnable threads before returning to this thread.
Happens all the time. It is what windows does. No problem there. What Sleep() does allow is for the message handler to return and the message pump to do its job while, in this case, his code is waiting for data to be available.
============================== Nothing to say.
-
Chuck O'Toole wrote:
Sleep() adds code to the loop,
Where as Peekmessage()/TranslateMessage()/DispatchMessage() does what? :)
Chuck O'Toole wrote:
even with Sleep(0) to quit the timeslice, still causes a complete scheduler cycle to look for other runnable threads before returning to this thread.
Happens all the time. It is what windows does. No problem there. What Sleep() does allow is for the message handler to return and the message pump to do its job while, in this case, his code is waiting for data to be available.
============================== Nothing to say.
1st, stop being a smarta$$, do I need a lawyer to review things for you to read? Clearly Sleep() adds code for *no benefit to this application* whereas *Peek/translate/dispatch* are *beneficial* to this app. 2nd, it's clear that you haven't read all the messages here. This guy isn't using threads, although lots of people are encouraging him to do so at the cost of redoing his application. That may or not be a good thing for *HIM*. I'm not debating that. He's not getting back to his message pump *because* he's doing processing in his GUI handler. Sleep ain't gonna help that because there's no Message Pump to run. Period. He has to provide his own (or redesign his app). I showed him how to provide his own JUST AS MICROSOFT DOCUMENTS.
-
1st, stop being a smarta$$, do I need a lawyer to review things for you to read? Clearly Sleep() adds code for *no benefit to this application* whereas *Peek/translate/dispatch* are *beneficial* to this app. 2nd, it's clear that you haven't read all the messages here. This guy isn't using threads, although lots of people are encouraging him to do so at the cost of redoing his application. That may or not be a good thing for *HIM*. I'm not debating that. He's not getting back to his message pump *because* he's doing processing in his GUI handler. Sleep ain't gonna help that because there's no Message Pump to run. Period. He has to provide his own (or redesign his app). I showed him how to provide his own JUST AS MICROSOFT DOCUMENTS.
Chuck O'Toole wrote:
Clearly Sleep() adds code for *no benefit to this application* whereas *Peek/translate/dispatch* are *beneficial* to this app.
Sorry, thats total guff. Sleep() will do the job perfectly well with less lines of code and in a more logical fashion.
Chuck O'Toole wrote:
He's not getting back to his message pump *because* he's doing processing in his GUI handler. Sleep ain't gonna help that because there's no Message Pump to run
You are wrong. Putting a Sleep() in the dispatcher will let the message pump run because it will release the existing call to DispatchMessage().
Chuck O'Toole wrote:
there's no Message Pump to run. Period. He has to provide his own
Of course there is! He wouldnt HAVE a Windows applicaiton without a message pump!
============================== Nothing to say.
-
Chuck O'Toole wrote:
Clearly Sleep() adds code for *no benefit to this application* whereas *Peek/translate/dispatch* are *beneficial* to this app.
Sorry, thats total guff. Sleep() will do the job perfectly well with less lines of code and in a more logical fashion.
Chuck O'Toole wrote:
He's not getting back to his message pump *because* he's doing processing in his GUI handler. Sleep ain't gonna help that because there's no Message Pump to run
You are wrong. Putting a Sleep() in the dispatcher will let the message pump run because it will release the existing call to DispatchMessage().
Chuck O'Toole wrote:
there's no Message Pump to run. Period. He has to provide his own
Of course there is! He wouldnt HAVE a Windows applicaiton without a message pump!
============================== Nothing to say.
[updated to reflect a third experiment's results]
Erudite__Eric wrote:
Of course there is! He wouldnt HAVE a Windows applicaiton without a message pump!
I'm not that dumb. Maybe I should have said "no message pump for Sleep() to return to". Your statement that Sleep() will release the call to DispatchMessage() needs to be proven beyond simply asserting it is true so I ran an experiment. I have a "regressison tester" application that does many long running things. In one case, similar to this one, I'm just cross checking some datafiles and I need to keep a "status / log window up to date with the progress". So I have this function called at times in the processing loop.
void CRegressionTesterDlg::ProcessWindowMessages()
{
MSG msg;// Sleep(0);
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // let them see the message before we go into longer term wait
{
TranslateMessage(&msg); // translate it
DispatchMessage(&msg); // and let windows dispatch it to WinProc
}
}And I ran three tests, one with the code as originally written, once with Sleep() replacing the message loop, and once with all the code commentd out. All kept the window up to date when it was visible. However, the Sleep() case and the "no code" case both failed to process other windows messages, like minimizing, clicking on the task bar to bring the window back to the front, etc. All these are classic symptoms of not having the "message pump" run. So, I think that Sleep() does not do as you assert, it has no effect on the Windows Message Processing. Furthermore, Microsoft's documentation on Sleep() explicitly warns against using it during functions called by message processing as it may cause a hang or delay in processing. Personally, since Microsoft says to use PeekMessage() in their documentation for exactly these types of long running things, I'm sticking with that. And I think you need to run some experiments on your own.
-
[updated to reflect a third experiment's results]
Erudite__Eric wrote:
Of course there is! He wouldnt HAVE a Windows applicaiton without a message pump!
I'm not that dumb. Maybe I should have said "no message pump for Sleep() to return to". Your statement that Sleep() will release the call to DispatchMessage() needs to be proven beyond simply asserting it is true so I ran an experiment. I have a "regressison tester" application that does many long running things. In one case, similar to this one, I'm just cross checking some datafiles and I need to keep a "status / log window up to date with the progress". So I have this function called at times in the processing loop.
void CRegressionTesterDlg::ProcessWindowMessages()
{
MSG msg;// Sleep(0);
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // let them see the message before we go into longer term wait
{
TranslateMessage(&msg); // translate it
DispatchMessage(&msg); // and let windows dispatch it to WinProc
}
}And I ran three tests, one with the code as originally written, once with Sleep() replacing the message loop, and once with all the code commentd out. All kept the window up to date when it was visible. However, the Sleep() case and the "no code" case both failed to process other windows messages, like minimizing, clicking on the task bar to bring the window back to the front, etc. All these are classic symptoms of not having the "message pump" run. So, I think that Sleep() does not do as you assert, it has no effect on the Windows Message Processing. Furthermore, Microsoft's documentation on Sleep() explicitly warns against using it during functions called by message processing as it may cause a hang or delay in processing. Personally, since Microsoft says to use PeekMessage() in their documentation for exactly these types of long running things, I'm sticking with that. And I think you need to run some experiments on your own.
-
So you tested this by putting a sleep() in the one function that handles all the windows messages? ANd you call this a valid test?
============================== Nothing to say.
Whatever gave you that impression? Have you been following all of this? Of course that's not the place that handles all the windows messages NORMALLY. Just like any GUI based application, it's event driven by messages dispatched by the standard windows message pump. It's reacting to the "OnButtonClick()" events, just like anybody else. One of the clicks causes a long running validation process. It's that process, already called by the DispatchMessage(), that needs to keep the GUI responsive while it munges on the data files and reports progress. (As a side note, it also cares about the cancel button which sets a cancelled flag). The whole point of this thread of this post has been exactly that, a process, itself a "dispatched" message handler, that is taking a long time to do something. So a SECOND, NON-BLOCKING message pump is needed to allow for those backed up messages to be processed, JUST LIKE MICROSOFT SAYS TO DO. So, yes it's a valid test. It's not the loop that processes all the messages, and if you've been reading for comprehension, you'd see that. I no longer wish to play this game with you.
-
UINT_PTR timer = SetTimer(1 , 1000 , NULL); m_timeOut = FALSE; while(!m_rxBufferRecivied && !m_timeOut) { } KillTimer(timer); . . . void CMainFrame::OnTimer(UINT_PTR nIDEvent) { m_timeOut = TRUE; } In this code i wait in a while loop unil input buffer recieved. Before the loop i set a timer to wait maximum 1 second so the program wont stack in a loop(in case there is error receving buffer). If i remove the while loop timer callback function ONTimer works fine every second but with the loop the program stacks in a endless loop. What am i doing wrong? Thanks.
A Universal TCP Socket Class for Non-blocking Server/Clients Single Threaded The function PumpMessages() processes all Windows messages which arrive in the application so the GUI stays responsive although the code runs an endless loop:
// Set Timeout 50 ms
mi_Socket.Listen(0, ms32_Port, 50);while (...) // This loop runs in the GUI thread
{
PumpMessages(); // process Windows messagesDWORD u32\_Event; SOCKET h\_Socket; // ProcessEvents() returns after 50 ms or after an event was received DWORD u32\_Error = mi\_Socket.ProcessEvents(&u32\_Event, &h\_Socket, ....); if (u32\_Error == ERROR\_TIMEOUT) continue; if (u32\_Event & FD\_ACCEPT) { /\* A new client has connected \*/ } if (u32\_Event & FD\_READ) { /\* Data has been received \*/ } if (u32\_Event & FD\_CLOSE) { /\* A socket has closed \*/ } if (u32\_Error) { /\* handle error \*/ }
};
-
Whatever gave you that impression? Have you been following all of this? Of course that's not the place that handles all the windows messages NORMALLY. Just like any GUI based application, it's event driven by messages dispatched by the standard windows message pump. It's reacting to the "OnButtonClick()" events, just like anybody else. One of the clicks causes a long running validation process. It's that process, already called by the DispatchMessage(), that needs to keep the GUI responsive while it munges on the data files and reports progress. (As a side note, it also cares about the cancel button which sets a cancelled flag). The whole point of this thread of this post has been exactly that, a process, itself a "dispatched" message handler, that is taking a long time to do something. So a SECOND, NON-BLOCKING message pump is needed to allow for those backed up messages to be processed, JUST LIKE MICROSOFT SAYS TO DO. So, yes it's a valid test. It's not the loop that processes all the messages, and if you've been reading for comprehension, you'd see that. I no longer wish to play this game with you.
-
[updated to reflect a third experiment's results]
Erudite__Eric wrote:
Of course there is! He wouldnt HAVE a Windows applicaiton without a message pump!
I'm not that dumb. Maybe I should have said "no message pump for Sleep() to return to". Your statement that Sleep() will release the call to DispatchMessage() needs to be proven beyond simply asserting it is true so I ran an experiment. I have a "regressison tester" application that does many long running things. In one case, similar to this one, I'm just cross checking some datafiles and I need to keep a "status / log window up to date with the progress". So I have this function called at times in the processing loop.
void CRegressionTesterDlg::ProcessWindowMessages()
{
MSG msg;// Sleep(0);
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // let them see the message before we go into longer term wait
{
TranslateMessage(&msg); // translate it
DispatchMessage(&msg); // and let windows dispatch it to WinProc
}
}And I ran three tests, one with the code as originally written, once with Sleep() replacing the message loop, and once with all the code commentd out. All kept the window up to date when it was visible. However, the Sleep() case and the "no code" case both failed to process other windows messages, like minimizing, clicking on the task bar to bring the window back to the front, etc. All these are classic symptoms of not having the "message pump" run. So, I think that Sleep() does not do as you assert, it has no effect on the Windows Message Processing. Furthermore, Microsoft's documentation on Sleep() explicitly warns against using it during functions called by message processing as it may cause a hang or delay in processing. Personally, since Microsoft says to use PeekMessage() in their documentation for exactly these types of long running things, I'm sticking with that. And I think you need to run some experiments on your own.
Chuck O'Toole wrote:
So, I think that Sleep() does not do as you assert, it has no effect on the Windows Message Processing. Furthermore, Microsoft's documentation on Sleep() explicitly warns against using it during functions called by message processing as it may cause a hang or delay in processing.
I know that MSDN is sometimes wrong, but what I read about
Sleep()
, and what you may be already saying, is that it suspends the execution of the current thread, meaning that the current thread does NOTHING. So, in effect, it halts execution and processes no messages."One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous