SetConsoleCtrlHandler рутинная проблема - PullRequest
19 голосов
/ 04 сентября 2010

Я пишу консольное приложение на C ++.

Я использую SetConsoleCtrlHandler для прерывания закрытия и нажатия клавиш CTRL + C.Это позволяет всем моим потокам правильно останавливаться и выходить.

Один из потоков выполняет некоторое сохранение, которое требует некоторого времени для завершения, и у меня есть некоторый код для ожидания в подпрограмме обработки crtl консоли.MSDN указывает, что через 5 секунд должно появиться окно для CTRL_CLOSE_EVENT, но вместо этого мой процесс завершается.

Это также раздражает при отладке консольного приложения, так как процесс завершается до того, как вы сможете перейти, и я не знаю, чтоможет быть проблема (у меня Windows 7 64bit).

Также, как ни странно, если моя процедура возвращает TRUE (просто отключить действие close), она все равно закрывает приложение.Процедура вызывается, поэтому SetConsoleCtrlHandler был успешно установлен.

Например:

BOOL WINAPI ConsoleHandlerRoutine(DWORD dwCtrlType)
{
    if (dwCtrlType == CTRL_CLOSE_EVENT)
    {
        return TRUE;
    }

    return FALSE;
}

int _tmain(int argc, _TCHAR* argv[])
{
    BOOL ret = SetConsoleCtrlHandler(ConsoleHandlerRoutine, TRUE);

    while (true)
    {
        Sleep(1000);
    }
    return 0;
}

Есть идеи?

Ответы [ 5 ]

17 голосов
/ 10 апреля 2011

Похоже, вы больше не можете игнорировать запросы на закрытие в Windows 7.

Вы делаете , хотя получаете событие CTRL_CLOSE_EVENT, и с этого момента у вас есть 10 секунд, чтобы сделать все, что вам нужно сделать, прежде чем оно автоматически закроется. Таким образом, вы можете выполнять любую работу в обработчике или устанавливать глобальный флаг.

case CTRL_CLOSE_EVENT: // CTRL-CLOSE: confirm that the user wants to exit.
                       close_flag = 1;
                       while(close_flag != 2)
                         Sleep(100);
                       return TRUE;

Забавный факт: пока код в вашем событии CTRL_CLOSE_EVENT выполняется, основная программа продолжает работать. Таким образом, вы сможете проверить флаг и выполнить 'close_flag = 2;' где-то. Но помните, у вас есть только 10 секунд. (Имейте в виду, что вы не хотите, например, прерывать основной поток программ, ожидающих ввода с клавиатуры.)

3 голосов
/ 12 июня 2014

Нет необходимости ждать какого-либо флага из основного потока, обработчик завершается, как только основной поток выходит (или через 10 секунд).

3 голосов
/ 02 марта 2012

Комментарий Ксавье немного ошибочен.Windows 7 позволяет вашему коду в обработчике событий ~ 10 секунд.Если вы не вышли из обработчика событий в течение 10 секунд, вы завершаете работу.Если вы выйдете из обработчика события, вы немедленно прекратите работу.Возврат ИСТИНЫ не выводит диалог.Он просто выходит.

3 голосов
/ 04 сентября 2010

Я подозреваю, что это не совсем так в Windows 7 - если пользователь хочет выйти из вашего приложения, вы не можете сказать ему "Нет"

1 голос
/ 04 сентября 2010

Вы делаете это более сложным, чем нужно.Я не знаю точно, почему ваше приложение закрывается, но SetConsoleCtrlHandler(NULL, TRUE) должен делать то, что вы хотите:

http://msdn.microsoft.com/en-us/library/ms686016(VS.85).aspx

Если параметр HandlerRoutine имеет значение NULL, значение TRUEзаставляет вызывающий процесс игнорировать ввод CTRL + C, а значение FALSE восстанавливает нормальную обработку ввода CTRL + C.

...