tags:

views:

143

answers:

5

Hi, 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!

+13  A: 

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.

Pablo Santa Cruz
+5  A: 

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

Im0rtality
In windows, it is `GetMessage`/`DispatchMessage`
sje397
+4  A: 

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;
            } 
        } 
    }
}
AOI Karasu
+3  A: 

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.

Hans Passant
+1  A: 

As a variation of AOI Karasu's answer, MFC has CWinThread::PumpMessage().

I use it in worker thread loops to keep them responsive. It works great.

JustBoo