Пример: обработчик управляющих сигналов консоли

Пример: обработчик управляющих сигналов консоли

В программе 4.5 организован бесконечный цикл, в котором каждые 5 секунд вызывается функция Веер, подающая звуковой сигнал. Пользователь может завершить выполнение программы, нажав комбинацию клавиш <Ctrl+C> или закрыв консоль. Процедура обработчика выводит на экран сообщение, выжидает 10 секунд, после чего, казалось бы, выполнение программы должно завершиться с возвратом значения TRUE. Однако в действительности основная программа обнаруживает флаг Exit и останавливает процесс. Это демонстрирует параллельную природу выполнения процедуры обработчика; заметьте, что объем выходной информации обработчика сигналов зависит от временных характеристик сигнала. Обработчики управляющих сигналов консоли будут использоваться также в примерах, приводимых в следующих главах.

Обратите внимание на использование макроса WINAPI; он применяется к пользовательским функциям, передаваемым в качестве аргументов функциям Windows, чтобы гарантировать выполнение соответствующих соглашений о вызовах. Этот макрос определен в заголовочном файле Microsoft С WTYPES.Н.

Программа 4.5. Ctrlc: программа обработки сигналов 

/* Глава 4. Ctrlc.с */

/* Перехватчик событий консоли. */

#include "EvryThng.h"

static BOOL WINAPI Handler(DWORD CtrlEvent); /* См. WTYPES.H. */

volatile static BOOL Exit = FALSE;

int _tmain(int argc, LPTSTR argv[])

 /* Периодическая подача звукового сигнала до поступления сигнала о прекращении выполнения. */

{

 /* Добавить обработчик событий. */

 if (!SetConsoleCtrlHandler(Handler, TRUE)) ReportError(_T("Ошибка при установке обработчика событий."), 1, TRUE);

 while (!Exit) {

  Sleep (5000); /* Подача звукового сигнала каждые 5 секунд. */

  Веер(1000 /* Частота. */, 250 /* Длительность. */);

 }

 _tprintf(_T("Прекращение выполнения программы по требованию. "));

 return 0;

}

BOOL WINAPI Handler (DWORD CtrlEvent) {

 Exit = TRUE;

 switch (CntrlEvent) {

 /* Увидите ли вы второе сообщения обработчика, зависит от соотношения временных параметров. */

 case CTRL_C_EVENT:

  _tprintf(_T("Получен сигнал Ctrl-c. Выход из обработчика через 10 секунд. "));

  Sleep(4000); /* Уменьшите это значение, чтобы получить другой эффект. */

  _tprintf(_T("Выход из обработчика через 6 секунд. "));

  Sleep(6000); /* Попробуйте уменьшить и это значение. */

  return TRUE; /* TRUE указывает на успешную обработку сигнала. */

 case CTRL_CLOSE_EVENT:

  _tprintf(_T("Выход из обработчика через 10 секунд. "));

  Sleep(4000);

  _tprintf(_Т ("Выход из обработчика через 6 секунд. "));

  Sleep (6000); /* Попробуйте уменьшить и это значение. */

  return TRUE; /* Попробуйте возвратить FALSE. Приводит ли это к изменению поведения программы? */

 default:

  _tprintf(_T("Событие: %d. Выход из обработчика через 10 секунд. "), CntrlEvent);

  Sleep(4000);

  _tprintf(_T("Выход из обработчика через 6 секунд. "));

  Sleep(6000);

  return TRUE;

 }