Ваша проблема в том, что вы создаете work
как переменную в стеке. work
сообщает io_service, что еще предстоит проделать работу. Из руководства:
Деструктор уведомляет io_service, что работа завершена.
Поскольку работа в main выполняется в стеке, срок ее службы больше, чем вы хотите. Он не будет разрушен до тех пор, пока главные выходы. Вместо этого создайте его в куче, чтобы вы могли явно уничтожить его. Измените его на:
using namespace boost::asio;
boost::scoped_ptr<io_service::work> work(new io_service::work(ioService));
Затем, позже, когда вы захотите сказать io_service остановиться после того, как он завершил всю оставшуюся работу, не останавливайте io_service, а вместо этого уничтожьте 'work', затем дождитесь завершения потока.
work.reset();
threadpool.join_all();
Это вызовет ~work()
, который удалит рабочий объект из io_service. Это, в свою очередь, приведет к выходу io_service::run
после завершения последней ожидающей операции.
Еще несколько заметок:
- Я бы не стал давать переменной то же имя, что и у ее класса. Я бы не стал писать
io_service::work work(io_service);
Это слишком запутанно. Я бы написал что-то вроде io_service::work some_work(io_service);
- Будьте осторожны с
io_service.post(... std::ref(str));
Вы передаете ссылку на действие post io_service. Переменная str должна жить достаточно долго для завершения задачи. Я уверен, что это здесь только для примера. В реальных приложениях может быть на удивление трудно гарантировать, что параметры, передаваемые рабочим объектам, не будут преждевременно разрушены. Я много использую shared_ptr<>
или, в случаях, когда это невозможно, иногда подсчитываю количество ожидающих действий io_service с boost :: atomic