Я использую boost :: asio для сбора очень простых пакетов UDP. Объект io_service создается в рабочем потоке, а io_service.run () вызывается изнутри этого потока. Моя проблема заключается в том, чтобы заставить io_service.run () возвращаться, когда я закончил сбор пакетов.
I ' Мне непонятно, какие методы io_service можно вызывать из других потоков, когда приходит время останавливать мой рабочий поток. У меня есть ссылка на объект io_service, и я делаю этот вызов из другого потока:
ios.dispatch( boost::bind( &udp_server::handle_kill, this ) );
В моем классе udp_server обработчик этой функции отменяет отложенную работу с помощью одного boost :: asio :: ip :: udp: : socket и один объект boost :: asio :: deadline_timer. Оба должны выполнить асинхронную работу. В этот момент я вызываю ios.stop ():
void udp_server::handle_kill()
{
m_socket.cancel();
m_timer.cancel();
m_ios.stop();
}
Поскольку никаких незавершенных работ нет, я ожидаю, что мой вызов ios.run () должен вернуться, но этого не происходит.
Так почему же этого не происходит. возвращение? Наиболее вероятное объяснение для меня состоит в том, что я не должен вызывать io_service :: dispatch () из другого потока. Но похоже, что метод dispatch () был создан именно для этого - отправлять вызов функции в потоке, который io_service :: run () работает. И, похоже, именно это и делает.
Таким образом, у меня возникает несколько связанных вопросов:
asio ведет себя для меня довольно хорошо, но мне нужно лучше понять этот элемент архитектуры.
socket :: udp :: cancel () очевидно неподдерживаемая операция над открытым сокетом под Win32 - поэтому эта операция завершается неудачно, вызывая исключение - что на самом деле вызывает выход из io_service :: run (), но определенно не является желаемым выходом.
socket :: udp :: close (), похоже, не отменяет отложенную задачу async_receive_from (), поэтому вызов его вместо socket :: udp :: cancel (), кажется, оставляет поток где-то внутри io_service :: run ().