下面的简单 async_wait 示例给出了
Operation canceled
错误。
#include <iostream>
#include <boost/asio.hpp>
void waitForTimer(boost::asio::io_context& ioContext) {
boost::asio::steady_timer timer(ioContext, boost::asio::chrono::seconds(1));
timer.async_wait([&](const boost::system::error_code& error) {
if (!error) {
std::cout << "Timer expired! Asynchronous wait complete." << std::endl;
waitForTimer(ioContext); // Recursive call for infinite loop
} else {
std::cerr << "Error: " << error.message() << std::endl;
}
});
}
int main() {
std::cout << "Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minor version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
boost::asio::io_context ioContext;
// Start the initial timer wait
waitForTimer(ioContext);
// Run the io_context to start asynchronous operations
ioContext.run();
return 0;
}
Using Boost 1.82.0
Error: Operation canceled
我只想用无限循环运行那个简单的 async_wait 示例。但它不起作用。
operation_canceled
是取消异步操作导致的。
销毁 IO 对象、调用
cancel
或在绑定的cancel_slot 上发出取消信号都可能取消异步操作。
此外,一些 IO 对象记录了隐式取消。例如。更改计时器对象的到期时间会隐式取消挂起的等待,例如
expiress_from_now
:
任何挂起的异步等待操作都将被取消。每个取消操作的处理程序将使用 boost::asio::error::operation_aborted 错误代码调用。
您的代码有一个局部变量
timer
。析构函数在函数返回之前运行,取消计时器。延长使用寿命,解决问题!
auto timer = make_shared<asio::steady_timer>(ioc, 1s);
timer->async_wait([timer, &ioc](boost::system::error_code const& error) {
if (!error) {
std::cout << "Timer expired! Asynchronous wait complete." << std::endl;
waitForTimer(ioc); // Recursive call for infinite loop
} else {
std::cerr << "Error: " << error.message() << std::endl;
}
});
看到它在Coliru上直播
虽然创建一个模拟您想要的循环定时器的类似乎更高效/优雅,但可以防止重复实例化和分配。
IntervalTimer
使一切更易于使用和可重复使用。在这里,演示 2 个具有不同间隔(1.5 秒和 4 秒)的同步计时器:
#include <boost/asio.hpp>
namespace asio = boost::asio;
using namespace std::chrono_literals;
struct IntervalTimer {
using timer = asio::steady_timer;
using duration = timer::duration;
using callback = std::function<void()>;
IntervalTimer(asio::any_io_executor ex, duration interval, callback cb)
: ival_(interval)
, timer_(ex, ival_)
, cb_(std::move(cb))
{
start();
}
private:
void start() {
timer_.expires_from_now(ival_);
timer_.async_wait([this](boost::system::error_code ec) {
if (!ec) {
if (cb_)
cb_();
start();
}
});
}
duration ival_;
timer timer_;
callback cb_;
};
#include <iostream>
#include <iomanip>
void trace(std::string_view msg) {
static constexpr auto now = std::chrono::steady_clock::now;
static auto const start = now();
std::cout << std::fixed << std::setprecision(2) << msg << " at " << (now() - start) / 1.s << "s"
<< std::endl;
}
int main() {
asio::io_context ioc;
// Start the initial timer wait
IntervalTimer timer1(ioc.get_executor(), 1500ms, []{ trace("timer 1 fired"); });
IntervalTimer timer2(ioc.get_executor(), 4s, []{ trace("timer 2 fired"); });
// Run the io_context to start asynchronous operations
ioc.run_for(10s);
}
打印
timer 1 fired at 1.50s
timer 1 fired at 3.00s
timer 2 fired at 4.00s
timer 1 fired at 4.50s
timer 1 fired at 6.00s
timer 1 fired at 7.50s
timer 2 fired at 8.00s
timer 1 fired at 9.00s
为了使
IntervalTimer
也具有动态生命周期,您可以使用enable_shared_from_this
:Live On Coliru
struct IntervalTimer : std::enable_shared_from_this<IntervalTimer> {
using timer = asio::steady_timer;
using duration = timer::duration;
using callback = std::function<void()>;
IntervalTimer(asio::any_io_executor ex, duration interval, callback cb)
: ival_(interval)
, timer_(ex, ival_)
, cb_(std::move(cb)) {}
void start() {
timer_.expires_from_now(ival_);
timer_.async_wait([this, self = shared_from_this()](boost::system::error_code ec) {
if (!ec) {
if (cb_)
cb_();
start();
}
});
}
private:
duration ival_;
timer timer_;
callback cb_;
};
具有相同的输出。