02-Timer.2-Using a timer asynchronouusly
本教程程序通过修改教程Timer.1中的程序,演示了如何使用asio的异步功能来对计时器执行异步等待。
#include <asio.hpp>
#include <iostream>
#include <spdlog/spdlog.h>
// 使用asio的异步功能意味着需要提供一个完成令牌,它决定了异步操作完成时如何将结果传递给完成处理程序。
// 在本程序中,我们定义了一个名为print的函数,它将在异步等待完成时被调用。
void print(const std::error_code& error)
{
// 如果有错误,则打印错误信息
if(error)
{
spdlog::error("Error[{}]: {}", error.value(), error.message());
return;
}
// 正常退出,打印计时器已过期
spdlog::info("Timer expired");
}
int main(int argc, char* argv[])
{
spdlog::info("Start wait 5 seconds");
asio::io_context io;
asio::steady_timer t(io, std::chrono::seconds(5));
// 接下来,与教程Timer.1中的阻塞等待不同,我们调用steady_timer::async_wait()函数来执行异步等待。
// 调用该函数时,我们传入之前定义的print函数。
t.async_wait(&print);
// 最后,我们必须在io_context对象上调用asio::io_context::run()成员函数。
//
// asio库保证完成处理程序只会从当前正在调用asio::io_context::run()的线程中被调用。
// 因此,除非调用了asio::io_context::run()函数,否则异步等待完成的完成处理程序将永远不会被调用。
//
// asio::io_context::run()函数在有“工作”要完成时也会继续运行。
// 在这个例子中,工作就是定时器的异步等待,因此该调用在定时器到期且完成处理程序返回之前不会退出。
//
// 重要的是要记住,在调用 asio::io_context::run() 之前,需要给 io_context 分配一些任务。
// 例如,如果我们省略了上面 steady_timer::async_wait() 的调用,io_context 就没有任何工作可做,
// 因此 asio::io_context::run() 会立即返回。
io.run();
spdlog::info("Hello, world!");
return 0;
}