Подтвердить что ты не робот

Проблема с SetConsoleCtrlHandler

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

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

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

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

Кроме того, как ни странно, если моя процедура возвращает 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;
}

Любые идеи?

4b9b3361

Ответ 1

Похоже, вы больше не можете игнорировать запросы на закрытие 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 секунд. (Поэтому имейте в виду, что вы не хотите повесить ваш основной поток программы, ожидающий ввода на клавиатуре, например.)

Ответ 2

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

Ответ 3

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

Ответ 4

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

BOOL WINAPI ConsoleHandler(DWORD dwType)
{
    switch(dwType) {
    case CTRL_CLOSE_EVENT:
    case CTRL_LOGOFF_EVENT:
    case CTRL_SHUTDOWN_EVENT:

      set_done();//signal the main thread to terminate

      //Returning would make the process exit!
      //We just make the handler sleep until the main thread exits,
      //or until the maximum execution time for this handler is reached.
      Sleep(10000);

      return TRUE;
    default:
      break;
    }
    return FALSE;
}

Ответ 5

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

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

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