2017-01-19 1 views
0

У меня есть основной цикл, и у меня есть функция, которая отображает меню с некоторыми вариантами и ждет ввода пользователя.
Дело в том, что я также должен проверить, произошло ли новое событие - в моем конкретном случае получено новое сообщение, но это совсем не актуально -, и я не могу дождаться пользователя выполните действие: я должен реализовать тайм-аут для этой функции.Прерывать функцию внутри основного цикла через определенное время

Вот простой пример того, что я говорю о:

int choice; 

for(;;){ 

    /* a new message could be arrived and we should read it now ... */ 

    choice = menu_function(); 

    /* 
     ...but the user still hasn't made an action, 
     so the menu_function() hasn't returned yet. 
    */ 

    switch(choice){ 
     case 1: 
      break; 
     case 2: 
      break; 
     default: 
      break; 
    } 
} 

До сих пор я думал использовать fork() перед menu_function() и kill() этот процесс после того, как он получил SIGALRM сигнал через alarm(), но дон Думаю, это правильное решение, поскольку оно находится внутри цикла.

Какое решение я должен принять?

P.S. Я не думаю, что это дубликат, поскольку, как я уже сказал, запрос прерывания функции находится внутри цикла. Или, по крайней мере, для меня, я думаю, что это совсем другое дело.

+0

Возможный дубликат [Как установить тайм-аут для функции в C?] (Http://stackoverflow.com/questions/7738546/how-to-set-a-timeout-for-a-function-in- c) – iwaduarte

ответ

1

Поскольку вы упоминаете fork Я предполагаю, что вы находитесь в системе POSIX (например, Linux или macOS)?

Это означает, что вы можете установить обработчик сигнала для SIGALRM в процессе делают ожидание и прием сигнала должен прервать операцию блокировки (с errno == EINTR), которые вы можете проверить и иметь menu_function возвращает значение значения " Выход". Код в вашем цикле мог бы проверить это значение и break вне цикла.

Другая альтернатива заключается в том, чтобы не использовать стандартные функции ввода C, если нет действительно что-то для чтения. Вы можете сделать это, используя вызов select с требуемым таймаутом и опрос FILENO_STDIN. Если функция select вернется с таймаутом, снова дайте menu_function вернуть специальное значение, означающее «exit», иначе он будет использовать стандартную функцию C для считывания и анализа данных.

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

+0

спасибо, вот что я искал. Я попробую и дам вам знать! – UrbiJr

+0

Извините, но я думаю, что я не очень хорошо понял. Как я могу вернуть значение из 'menu_function', когда он получает' SIGALRM'? Я имею в виду, что я написал функцию handle_sigalrm, но я не знаю, что с этим делать. Кроме того, я не обращал внимания, когда вы упомянули 'break': где я должен его использовать? Если бы вы могли сделать пример - просто заполнив мой пример правильным кодом - я бы наверняка отметил ваш ответ как решение, но пока я все еще застрял ... – UrbiJr

+0

@UrbiJr Когда вы используете, например, 'scanf' он будет где-то застревать на' read', ожидая появления символов на стандартном входе. Когда вы получите 'SIGALRM', тогда вызов' read' будет прерван, и если сигнал будет инициализирован, чтобы не перезапустить прерванную функцию, тогда 'read' вернется с ошибкой и' errno' будет установлен в 'EINTR'. Это будет передано функции 'scanf', которая, в свою очередь, вернет вам' EOF'. Если ваш 'menu_function' вызывает' scanf', он может проверить это условие и вернуться. Сам обработчик сигнала вообще ничего не должен делать, его тело может быть пустым. –

Смежные вопросы