Как остановить процесс с помощью кнопки «Стоп» - PullRequest
8 голосов
/ 05 августа 2010

Я создал простое окно с двумя кнопками, первый вызывает функцию, которая длится долго, второй устанавливает значение переменной «stop» в TRUE, изначально было установлено значение ЛОЖЬ.

Мое намерение состоит в том, чтобы, нажимая первую кнопку, она запускает долгий процесс, это контролирует, если переменная останова установлена ​​в TRUE или FALSE для каждого цикла, если значение 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 () там и так? (Я новичок :))

Спасибо!

Ответы [ 5 ]

13 голосов
/ 05 августа 2010

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

Это вместо простого вызова longProcess функции при Нажмите кнопку Пуск , создайтенить и запустить длинный процесс на нем.

Что происходит, так это то, что ваш длительный процесс блокирует ваш поток пользовательского интерфейса, который отвечает за обработку событий пользовательского интерфейса.Таким образом, Нажатие кнопки «Стоп» не будет обработано, пока не закончится longProcess().

5 голосов
/ 05 августа 2010

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

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

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

    ProcessPendingMessages();
}

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

3 голосов
/ 05 августа 2010

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

3 голосов
/ 05 августа 2010

Как насчет использования 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;
            } 
        } 
    }
}
1 голос
/ 05 августа 2010

В качестве варианта ответа АОИ Карасу, MFC имеет CWinThread :: PumpMessage ().

Я использую его в циклах рабочих потоков, чтобы они оставались отзывчивыми. Отлично работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...