2017-02-20 34 views
1

Я пытаюсь поймать Ctrl-C на в приложении, как показано в следующем MWEИспользование повысить ASIO поймать Ctrl-C

#include <boost/asio/signal_set.hpp> 
#include <iostream> 

void handler(const boost::system::error_code& error , int signal_number) 
{ 
    std::cout << "handling signal " << signal_number << std::endl; 
} 

int main(int argc , char** argv) 
{ 
    boost::asio::io_service io_service; 

    // Construct a signal set registered for process termination. 
    boost::asio::signal_set signals(io_service, SIGINT); 

    // Start an asynchronous wait for one of the signals to occur. 
    signals.async_wait(handler); 

    char choice; 
    while(true) 
    { 
     std::cout << "Press a key: " << std::endl; 
     std::cin >> choice; 
    } 
} 

К сожалению handler() не вызывается при нажатии Ctrl +C. не наоборот цикл больше не ожидает ввода пользователя, как показано ниже:

c:\tmp>CtrlC.exe 
Press a key: 
d 
Press a key: 
e 
Press a key: 
Press a key: 
Press a key: 
Press a key: 
Press a key: 
Press a key: 
Press a key: 
Press a key: 
Press a key: 

Если это имеет значение, я на Windows, и я знаю, что есть Windows, специфический способ поймать Ctrl + C но я хотел бы использовать boost, если это возможно, для удобства переноса.

+0

Вашего 'станд :: CIN >>' является блокирующей операцией. В настоящий момент io_service не работает. – PSIAlt

ответ

2

увеличить ASIO в центре на объекте io_service, все задачи, которые вы запрашиваете (особенно асинхронные), обычно обрабатываются io_service.

Поступая:

// Start an asynchronous wait for one of the signals to occur. 
signals.async_wait(handler); 

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

Дело в том, что ваш io_service не работает.

Так что, если вы хотите, чтобы правильно работать, вы должны запустить его:

#include <boost/asio/signal_set.hpp> 
#include <iostream> 

void handler(const boost::system::error_code& error , int signal_number) 
{ 
    std::cout << "handling signal " << signal_number << std::endl; 
    exit(1); 
} 

int main(int argc , char** argv) 
{ 
    boost::asio::io_service io_service; 

    // Construct a signal set registered for process termination. 
    boost::asio::signal_set signals(io_service, SIGINT); 

    // Start an asynchronous wait for one of the signals to occur. 
    signals.async_wait(handler); 

    io_service.run(); 
} 

Затем нажатием Ctrl + C будет делать то, что вы ожидаете.

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

+0

Я завернул. Настройте цикл infinte в функции, называемой 'func', и передайте ее в io_service, например, так:' io_service.post (func) ', но я получаю тот же результат. – Olumide

+1

ваш бесконечный цикл - это 'io_service', не помещайте еще один бесконечный цикл внутри, только ставьте действие, которое хотите сделать, и если вы хотите, чтобы он повторялся, перетащите его, когда он будет завершен. – Drax

+0

Как отправить сообщение? Я получаю бесконечный цикл, если я делаю это в 'func()'. – Olumide

1

Необходимо передать io_service обработчикам, которые были переданы ему. io_service может надеть это, только если вы позвоните по телефону run или run_one. Вы можете использовать метод run_one внутри время цикла:

#include <boost/asio/signal_set.hpp> 
#include <iostream> 
#include <cstdlib> 
#include <limits> 

void handler(const boost::system::error_code& error , int signal_number) 
{ 
    // Not safe to use stream here... 
    std::cout << "handling signal " << signal_number << std::endl; 
    exit (1); 
} 

int main(int argc , char** argv) 
{ 
    boost::asio::io_service io_service; 

    // Construct a signal set registered for process termination. 
    boost::asio::signal_set signals(io_service, SIGINT); 

    // Start an asynchronous wait for one of the signals to occur. 
    signals.async_wait(handler); 

    char choice; 
    while(true) 
    { 
     std::cout << "Press a key: " << std::endl; 
     std::cin >> choice; 
     io_service.run_one(); 
    } 
} 
+0

Небезопасно использовать 'cout' в обработчике в этом конкретном случае? Существует только один поток выполнения. –

+0

Нет, вы никогда не знаете, в какой момент вызывается обработчик сигналов. Что делать, если в буфере потока cout уже были частично записаны данные до вызова обработчика? В моем случае эффект, вероятно, менее суровый, но лучше избегать доступа к любому совместно используемому ресурсу в обработчике сигналов. – Arunmu

+1

Вы говорите о «сигналах в стиле POSIX»? Я уверен, что Boost.Asio не вызывает обработчик, передаваемый 'signal.async_wait' из обработчика сигнала (POSIX). Поэтому я не вижу, как обработчик может быть вызван, пока есть «частично записанные данные в буфере потока' cout ». Но я согласен, что лучше избегать. –