Boost asio - остановка io_service

Я использую 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 () работает. И, похоже, именно это и делает.

Таким образом, у меня возникает несколько связанных вопросов:

  1. Правильно ли я использую io_service :: dispatch ()?
  2. Если все задачи отменены , есть ли причина, по которой io_service :: run () не должен возвращать?
  3. socket :: upd :: cancel () не кажется правильным способом закрыть сокет и прервать всю работу. Каков правильный путь?

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

Больше данных

socket :: udp :: cancel () очевидно неподдерживаемая операция над открытым сокетом под Win32 - поэтому эта операция завершается неудачно, вызывая исключение - что на самом деле вызывает выход из io_service :: run (), но определенно не является желаемым выходом.

socket :: udp :: close (), похоже, не отменяет отложенную задачу async_receive_from (), поэтому вызов его вместо socket :: udp :: cancel (), кажется, оставляет поток где-то внутри io_service :: run ().

18
задан Sam Miller 21 March 2013 в 03:24
поделиться