Подтвердить что ты не робот

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

Я использую boost:: asio для создания очень простой коллекции пакетов UDP. Объект io_service создается в рабочем потоке, и изнутри этого потока вызывается io_service.run(). Моя проблема заключается в том, чтобы вернуть io_service.run(), когда я закончил сбор пакетов.

Я не понимаю, какие методы io_service можно вызывать из других потоков, когда приходит время остановить мой рабочий поток. У меня есть ссылка на объект io_service, и из другого потока я делаю этот вызов:

ios.dispatch( boost::bind( &udp_server::handle_kill, this ) );

В моем классе udp_server обработчик этой функции отменяет ожидающую работу из одного boost:: asio:: ip:: udp:: socket и одного объекта boost:: asio:: deadline_timer. Оба имеют ожидающую работу async. В этот момент я вызываю 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(). И это похоже на то, что.

Итак, это оставляет мне несколько связанных вопросов:

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

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

Дополнительные данные

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

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

4b9b3361

Ответ 1

Вызов io_service::stop из другого потока безопасен, это хорошо описано в документации

Безопасность резьбы

Отдельные объекты: безопасно.

Общие объекты: безопасно, с исключение, вызывающее reset(), в то время как есть незавершенные run(), run_one(), poll() или poll_one() вызывает результаты undefined.

как указывают комментарии к вашему вопросу, вам действительно нужно сварить это до воспроизводимого примера.