Вы написали в комментарии, что cancel
будет отменять инициацию асинхронной операции, но expires_at
делает то же самое (см. ссылка , Все ожидающие асинхронные операции ожидания будет отменено ).
Asyn c Операция, запущенная в thread1
по async_write
, может быть отменена при вызове expires_at
из потока main
. Этот лог c просто неверен, также, если вы хотите сделать это, вы должны использовать mutex для защиты одновременного доступа к steady_timer
(общий экземпляр не является поточно-ориентированным - (см. reference ), Общие объекты: небезопасно. ).
Единственный безопасный способ остановить бесконечную цепочку вызовов функции print
- добавить к функции print
некоторое условие остановки.
Вы можете заключить steady_timer
в структуру с atomic<bool> finish
переменной-членом. По истечении 20 секунд вы устанавливаете этот элемент и проверяете его в функции print
при обработке последнего вызова обработчика. Таким образом, вы уверены, что будет вызван весь запущенный обработчик.
struct Foo {
boost::asio::steady_timer timer;
std::atomic<bool> finish{false};
template<class Expire>
Foo(boost::asio::io_context& io, Expire expire) : timer(io, expire) {}
};
void print(const boost::system::error_code& e, Foo* foo, int* count) {
if (foo->finish)
return;
std::cout << "every 2 seconds i count " << (*count)++ << " counts\n";
foo->timer.expires_at(foo->timer.expiry() + chrono::seconds(2));
foo->timer.async_wait(boost::bind(print, boost::asio::placeholders::error, foo, count));
}
int main() {
int count = 0;
io_context my_context;
Foo foo(my_context, std::chrono::seconds(2));
foo.timer.async_wait(boost::bind(print, boost::asio::placeholders::error, &foo, &count));
std::thread thread1( [&my_context]() {my_context.run(); } );
Sleep(20000); // 20 s
foo.finish = true;
thread1.join();
Другое решение - добавить дополнительный параметр в функцию print
, например, с именем: bool asTheLastOne
. Каждый раз, когда вы запускаете async_write
с print
, вы решаете, будет ли эта операция последней.