Я следил вместе с этим превосходным учебным пособием по asio , но запутался именно с тем, что делают пряди. Насколько я понимаю, они работали как очередь для набора обработчиков (обратных вызовов), так что обработчики в такой очереди выполнялись бы по порядку. Но некоторые эксперименты показывают, что я не прав. Может кто-нибудь объяснить, кто они на самом деле?
Я начинаю с , пример 6c Он выполняет от PrintNum(1)
до PrintNum(5)
, каждый с задержкой в 1 секунду, перед запуском таймера. (Необязательно, это также происходит, если я переместил вызовы PrintNum после запуска таймера! Затем я понял, что запрос вызова TimerHandler не попадает в очередь очереди до тех пор, пока не сработает таймер.)
Моим первым вариантом было удалить ссылки на нити только по таймеру, но оставить их в PrintNum ( см. Полный код в gist ):
strand->post( boost::bind( &PrintNum, 1 ) );
strand->post( boost::bind( &PrintNum, 2 ) );
strand->post( boost::bind( &PrintNum, 3 ) );
strand->post( boost::bind( &PrintNum, 4 ) );
strand->post( boost::bind( &PrintNum, 5 ) );
boost::shared_ptr< boost::asio::deadline_timer > timer(
new boost::asio::deadline_timer( *io_service )
);
timer->expires_from_now( boost::posix_time::seconds( 1 ) );
timer->async_wait( boost::bind( &TimerHandler, _1, timer ) );
Теперь таймер работает независимо от вызовов PrintNum. Я получаю вывод, который ожидал.
У меня вопрос ко второму варианту ( см. Суть ), где я удалил вызовы прядей для PrintNum, но сохранил их в таймере:
io_service->post( boost::bind( &PrintNum, 1 ) );
io_service->post( boost::bind( &PrintNum, 2 ) );
io_service->post( boost::bind( &PrintNum, 3 ) );
io_service->post( boost::bind( &PrintNum, 4 ) );
io_service->post( boost::bind( &PrintNum, 5 ) );
boost::shared_ptr< boost::asio::deadline_timer > timer(
new boost::asio::deadline_timer( *io_service )
);
timer->expires_from_now( boost::posix_time::milliseconds( 1000 ) );
timer->async_wait(
strand->wrap( boost::bind( &TimerHandler, _1, timer, strand ) )
);
(Вы увидите в коде сущности, что я немного перемешал его, но поведение в основном такое же.)
То, что я ожидал здесь, это то, что цепочка в основном ничего не делает: я только один обработчик (TimerHandler) в очереди цепочки за раз. Поэтому я ожидал, что таймер отключится независимо от вызовов PrintNum. Но я вижу, что вызовы PrintNum по-прежнему имеют приоритет: все 5 должны завершиться, прежде чем TimerHandler будет разрешено выполнить.
(Стоит отметить, что пример 6c в учебном пособии Дрю Бентона был посвящен обеспечению того, чтобы ни TimerHandler, ни PrintNum не работали одновременно. Мои варианты намеренно снимают эту гарантию; моей отправной точкой было желание понять проблему, заключающуюся в том, что Пример 6с является решением.)