Как остановить процесс с помощью “Кнопки остановки”

Я создал простое окно с двумя кнопками, первый вызывает функцию, которая длится долгое время, второй устанавливает значение переменной "остановки" к ПРАВДА, который был первоначально установлен на ЛОЖЬ.

Мое намерение состоит в том, что, путем нажатия первой кнопки это выполняет долгий процесс, что средства управления, если переменная остановки имеет значение true или ЛОЖЬ для каждого цикла, если значением является TRUE функция, должны возвратиться, таким образом, процесс останавливается.

...

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;

    ...

}

}

Проблема состоит в том, что, когда я нажимаю первую кнопку, процесс запускается обычно, но когда я нажимаю вторую кнопку для остановки процесса, ничего не происходит, я заметил, что переменная остановки имеет значение true только после конца процесса. Я думал что, вероятно, в проблеме, связанной с очередью сообщений...

Каково могло быть лучшее решение??? Это корректно для вызова longProcess () там и таким образом? (I'am новичок :))

Спасибо!

8
задан mario 5 August 2010 в 12:35
поделиться

5 ответов

Вам нужно запустить длинный процесс в отдельном потоке, и ваш подход должен сработать.

То есть вместо того, чтобы просто вызвать функцию longProcess при нажатии кнопки Start, создайте поток и запустите длинный процесс в нем.

Происходит то, что ваш длинный процесс блокирует ваш поток UI, который отвечает за обработку событий UI. Так, щелчок кнопки Stop не будет обработан, пока не завершится longProcess().

13
ответ дан 5 December 2019 в 06:36
поделиться

В Delphi есть Application.ProcessMessages (), который в основном обрабатывает все ожидающие сообщения и возвращает. И вы можете включить эту строку в цикл, чтобы сделать UI более отзывчивым.

С помощью такой функции вы можете сделать это

while(stop == FALSE) {
     // do something
    ...

    ProcessPendingMessages();
}

РЕДАКТИРОВАТЬ: Это применимо, если вы не хотите разделять код для разделения потока - быстрое решение

5
ответ дан 5 December 2019 в 06:36
поделиться

Как насчет использования 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;
            } 
        } 
    }
}
3
ответ дан 5 December 2019 в 06:36
поделиться

Как минимум, вам нужно будет объявить свою переменную с помощью ключевого слова volatile . Но лучший способ сделать это - использовать событие. CreateEvent () для его инициализации, SetEvent () для сигнализации условия остановки, WaitForSingleObject () с таймаутом 0 для его проверки.

3
ответ дан 5 December 2019 в 06:36
поделиться

Как вариант ответа AOI Karasu, в MFC есть CWinThread::PumpMessage().

Я использую его в циклах рабочих потоков для поддержания их отзывчивости. Работает отлично.

1
ответ дан 5 December 2019 в 06:36
поделиться