I created a simple window with two buttons, the first one calls a function that lasts a long time, the second one sets the value of a variable "stop" to TRUE, that was initially set to FALSE.
My intention is that, by pressing the first button it runs a long process, that controls if the stop variable is set to TRUE or FALSE for every loop, if the value is TRUE the function should return, so the process is stopped.
...
static BOOL stop = FALSE; // My variable defined somewhere
...
int longProcess () // My function
{
while(stop == FALSE) {
// do something
}
return 0;
}
...
switch (msg)
{
case WM_CREATE:
{
...
Button1 = CreateWindowEx(0,
TEXT("BUTTON"),
TEXT("Start"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
100, 100, 100, 20,
hWnd,
(HMENU)BUTTON_START,
NULL,
NULL);
Button2 = CreateWindowEx(0,
TEXT("BUTTON"),
TEXT("Stop"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
200, 200, 100, 20,
hWnd,
(HMENU)BUTTON_STOP,
NULL,
NULL);
...
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case BUTTON_START:
longProcess(); // Starts the process
break;
case BUTTON_STOP:
stop = TRUE; // Should stop the process
break;
}
}
break;
...
}
}
The problem is that when I press the first button the process starts normally, but when I press the second button in order to stop the process nothing happens, I noticed that the stop variable is set to TRUE only after the end of the process. I thought that probably in a problem related to the message queue...
What could be the best solution??? It is correct to call longProcess() there and in that way? (I'am a newbie :) )
Thanks!
You need to run the long process on a separate thread and your approach should work.
This is, instead of just calling longProcess
function on Start Button Click, create a thread, and run the long process on it.
What's happening is that your long process is blocking your UI thread, which is responsible for handling UI events. So, Stop Button Click won't be handled until longProcess()
finishes.
In Delphi we have Application.ProcessMessages() which basically processes all pending messages and returns. And you can put this line to cycle to make UI more responsive.
With function like that you could do this
while(stop == FALSE) {
// do something
...
ProcessPendingMessages();
}
EDIT: This applies if you don't want to split code to separate thread - quick'n'dirty workaround
How about using PeekMessage?
int longProcess () // My function
{
while(stop == FALSE)
{
// do something
while (PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE))
{
// check for the stop button
if ((msg.message == WM_COMMAND) && (LOWORD(wParam) == BUTTON_STOP))
stop = TRUE;
}
}
}
}
At the very minimum, you'll have to declare your variable with the volatile keyword. But the best way to do it is to use an event. CreateEvent() to initialize it, SetEvent() to signal the stop condition, WaitForSingleObject() with a 0 timeout to test it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With