Timers and Asynchronous I/O
This section is the most important one in the entire Boost.Asio tutorial. Serial port, TCP, and UDP asynchronous models are similar to timers: you first register the asynchronous operation, and then
io_context.run()drives the callback execution.
All asynchronous callbacks in this section use std::bind, and do not use lambdas for now.
Example 1: Writing a synchronous timer in an ordinary main()
program objective
First, write the simplest blocking timer: after the program starts, immediately print a sentence, then block for 2 seconds, and then print a final message.
Full code
#include <boost/asio.hpp>
#include <chrono>
#include <iostream>
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer(io, std::chrono::seconds(2));
std::cout << "程序开始:准备等待 2 秒" << std::endl;
// 同步等待会阻塞当前线程,时间没到之前不会继续往下执行。
timer.wait();
std::cout << "2 秒到了:timer.wait() 返回" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo1_sync_timer.cpp -o demo1_sync_timer -std=c++17 -lboost_system -pthread
./demo1_sync_timer
Execution output and chronological order
程序开始:准备等待 2 秒
After waiting about 2 seconds:
2 秒到了:timer.wait() 返回
请提供您要翻译的简体中文 Markdown 片段。
程序开始:准备等待 2 秒
2 秒到了:timer.wait() 返回
Points to note for this example
This program does not demonstrate "asynchronous" behavior because timer.wait() directly blocks the current thread.
In other words, the program is stuck here:
timer.wait();
The next line will not execute until 2 seconds have passed.
Key Function Explanation
boost::asio::io_context io;
Purpose: Create an Asio event loop object.
In the synchronous wait() example, it doesn't seem very prominent; but in the asynchronous version, all asynchronous events rely on it to drive them.
boost::asio::steady_timer timer(io, std::chrono::seconds(2));
Purpose: Create a timer based on a stable clock, set to expire after 2 seconds.
Parameter:
io
Indicates which io_context manages this timer.
std::chrono::seconds(2)
Indicates expiration 2 seconds from the current time.
timer.wait();
Purpose: blocks until the timer expires.
Return value: void.
Features: Simple, but it will block the current thread. In a robot program, if written this way in the main control loop, it can easily hang the entire program.
Example 2: Writing an asynchronous timer in a regular main()
program objective
Rewrite Example 1 using asynchronous syntax:
- Register a 2-second timer;
async_wait()non-blocking;io.run()starts blocking;- The callback function is executed after 2 seconds;
- After no task,
io.run()returns.
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
void on_timer(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << "定时器被取消,错误信息:" << ec.message() << std::endl;
return;
}
std::cout << "回调函数 on_timer:2 秒到了" << std::endl;
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer(io, std::chrono::seconds(2));
std::cout << "main:注册 async_wait" << std::endl;
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer.async_wait(std::bind(on_timer, std::placeholders::_1));
std::cout << "main:async_wait 已经返回,但回调还没执行" << std::endl;
std::cout << "main:准备调用 io.run()" << std::endl;
io.run();
std::cout << "main:io.run() 返回,程序结束" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo2_async_timer.cpp -o demo2_async_timer -std=c++17 -lboost_system -pthread
./demo2_async_timer
Execution output and chronological order
The program immediately outputs:
main:注册 async_wait
main:async_wait 已经返回,但回调还没执行
main:准备调用 io.run()
Then the program gets stuck at:
io.run();
Wait about 2 seconds, then output:
回调函数 on_timer:2 秒到了
main:io.run() 返回,程序结束
请提供您要翻译的简体中文 Markdown 片段。
main:注册 async_wait
main:async_wait 已经返回,但回调还没执行
main:准备调用 io.run()
回调函数 on_timer:2 秒到了
main:io.run() 返回,程序结束
Points to note for this example
async_wait() does not wait for 2 seconds. It simply registers the event of "execute callback after 2 seconds" into io_context.
What truly awaits:
io.run();
So don't interpret async_wait() as an "asynchronous version of wait." More precisely:
async_wait() = 注册任务
io.run() = 执行事件循环
on_timer() = 任务完成后的回调
std::bind Description
This line of code:
timer.async_wait(std::bind(on_timer, std::placeholders::_1));
Meaning:
当 timer 到期后,Boost.Asio 会传入一个 error_code。
这个 error_code 会填到 std::placeholders::_1 的位置。
最后调用 on_timer(ec)。
on_timer's function signature must accept this parameter:
void on_timer(const boost::system::error_code& ec)
Key Function Explanation
timer.async_wait(handler)
Purpose: Register an asynchronous wait operation.
Parameter: a callback function object.
Return value: void.
Note: It will not block waiting for the timer to expire.
io.run()
Purpose: Start the event loop, handle asynchronous tasks and callback functions.
Return value: the number of executed handlers, the type can usually be considered as std::size_t.
In this example, io.run() executed one callback, so the return value is 1. We just didn't print the return value.
Example 3: Writing two asynchronous timers in a common main()
program objective
It's hard to perceive the feeling of asynchronous scheduling with just one timer, so this time we'll write two timers:
timer1expires in 1 second;timer2expires in 3 seconds;- Both timers are in the same
io_context; io.run()will wait until both tasks are completed before returning.
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
#include <string>
void on_timer(const boost::system::error_code& ec, const std::string& name)
{
if (ec)
{
std::cout << name << " 被取消:" << ec.message() << std::endl;
return;
}
std::cout << name << " 到期,执行回调" << std::endl;
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer1(io, std::chrono::seconds(1));
boost::asio::steady_timer timer2(io, std::chrono::seconds(3));
std::cout << "main:注册 timer1,1 秒后到期" << std::endl;
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer1.async_wait(std::bind(on_timer,
std::placeholders::_1,
std::string("timer1")));
std::cout << "main:注册 timer2,3 秒后到期" << std::endl;
timer2.async_wait(std::bind(on_timer,
std::placeholders::_1,
std::string("timer2")));
std::cout << "main:调用 io.run()" << std::endl;
std::size_t count = io.run();
std::cout << "main:io.run() 返回,一共执行了 " << count << " 个回调" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo3_two_timers.cpp -o demo3_two_timers -std=c++17 -lboost_system -pthread
./demo3_two_timers
Execution output and chronological order
The program immediately outputs:
main:注册 timer1,1 秒后到期
main:注册 timer2,3 秒后到期
main:调用 io.run()
Output in about 1 second:
timer1 到期,执行回调
After about another 2 seconds, i.e., about 3 seconds after program startup, output:
timer2 到期,执行回调
main:io.run() 返回,一共执行了 2 个回调
请提供您要翻译的简体中文 Markdown 片段。
main:注册 timer1,1 秒后到期
main:注册 timer2,3 秒后到期
main:调用 io.run()
timer1 到期,执行回调
timer2 到期,执行回调
main:io.run() 返回,一共执行了 2 个回调
Points to note for this example
Two timers are not two threads.
This example has only one thread, which is the main thread. The callbacks of timer1 and timer2 are both executed in this main thread that calls io.run().
The actual execution order is:
主线程进入 io.run()
等待事件
timer1 先到期 -> 调用 timer1 回调
继续等待事件
timer2 后到期 -> 调用 timer2 回调
没有任务了 -> io.run() 返回
Fixed parameters in std::bind
This sentence:
std::bind(on_timer, std::placeholders::_1, std::string("timer1"))
Equivalent to preparing a function object in advance:
未来 Asio 传入 ec 时,调用 on_timer(ec, "timer1")。
_1 is the error code that will be passed in by Asio in the future.
"timer1" is a parameter that is fixed right now.
Example 4: Writing a repeating timer in a normal main()
program objective
Implement a timer that prints once every 1 second, and ends after printing 5 times.
This example is very similar to a periodic task in a robot, for example:
每 20ms 发送一次速度命令
每 100ms 检查一次下位机心跳
每 1s 打印一次通信状态
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
void repeat_timer(const boost::system::error_code& ec,
boost::asio::steady_timer* timer,
int* count)
{
if (ec)
{
std::cout << "repeat_timer 被取消:" << ec.message() << std::endl;
return;
}
++(*count);
std::cout << "第 " << *count << " 次定时器回调" << std::endl;
if (*count < 5)
{
timer->expires_after(std::chrono::seconds(1));
timer->async_wait(std::bind(repeat_timer,
std::placeholders::_1,
timer,
count));
}
else
{
std::cout << "已经执行 5 次,不再重新注册定时器" << std::endl;
}
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer(io, std::chrono::seconds(1));
int count = 0;
std::cout << "main:注册第 1 次定时器" << std::endl;
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer.async_wait(std::bind(repeat_timer,
std::placeholders::_1,
&timer,
&count));
io.run();
std::cout << "main:io.run() 返回,程序结束" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo4_repeat_timer.cpp -o demo4_repeat_timer -std=c++17 -lboost_system -pthread
./demo4_repeat_timer
Execution output and chronological order
The program immediately outputs:
main:注册第 1 次定时器
About 1 second later:
第 1 次定时器回调
Then output approximately every 1 second:
第 2 次定时器回调
第 3 次定时器回调
第 4 次定时器回调
第 5 次定时器回调
已经执行 5 次,不再重新注册定时器
main:io.run() 返回,程序结束
请提供您要翻译的简体中文 Markdown 片段。
main:注册第 1 次定时器
第 1 次定时器回调
第 2 次定时器回调
第 3 次定时器回调
第 4 次定时器回调
第 5 次定时器回调
已经执行 5 次,不再重新注册定时器
main:io.run() 返回,程序结束
Points to note for this example
The repeating timer is not inside the while loop sleep.
The asynchronous syntax is:
第一次 async_wait
第 1 次回调里重新设置 expires_after
第 1 次回调里再次 async_wait
第 2 次回调里再次注册
……
That is, “before each callback ends, decide whether to register the next one.”
Pointer Lifecycle Explanation
In this example, passed:
&timer
&count
This is to allow repeat_timer() to modify the same timer and count.
This way of writing is safe in this example because:
timer 和 count 都是 main() 里的局部变量
main() 会卡在 io.run()
io.run() 返回前,timer 和 count 都不会析构
However, in engineering it is more recommended to encapsulate it into a class; see the next example.
Example 5: Writing a Single Asynchronous Timer in a Class
program objective
Convert Example 2 to a class-encapsulated version.
Class encapsulation is a more common approach in robot projects, for example:
SerialDriver 类
TcpClient 类
UdpReceiver 类
RobotController 类
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
class Printer
{
public:
explicit Printer(boost::asio::io_context& io)
: timer_(io, std::chrono::seconds(2))
{
std::cout << "Printer 构造:注册 2 秒定时器" << std::endl;
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer_.async_wait(std::bind(&Printer::on_timer,
this,
std::placeholders::_1));
}
private:
void on_timer(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << "Printer::on_timer 被取消:" << ec.message() << std::endl;
return;
}
std::cout << "Printer::on_timer:2 秒到了" << std::endl;
}
private:
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer_;
};
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
Printer printer(io);
std::cout << "main:准备调用 io.run()" << std::endl;
io.run();
std::cout << "main:io.run() 返回" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo5_class_timer.cpp -o demo5_class_timer -std=c++17 -lboost_system -pthread
./demo5_class_timer
Execution output and chronological order
The program immediately outputs:
Printer 构造:注册 2 秒定时器
main:准备调用 io.run()
Output in about 2 seconds:
Printer::on_timer:2 秒到了
main:io.run() 返回
请提供您要翻译的简体中文 Markdown 片段。
Printer 构造:注册 2 秒定时器
main:准备调用 io.run()
Printer::on_timer:2 秒到了
main:io.run() 返回
Constructor Initializer List Explanation
I see you've indicated "这段:" but didn't include the Chinese text to translate. Please provide the Chinese Markdown fragment you'd like me to translate into natural American English.
explicit Printer(boost::asio::io_context& io)
: timer_(io, std::chrono::seconds(2))
{
}
What follows the colon is called the "constructor initializer list."
Its role is: directly construct the member variable timer_ before entering the constructor's braces.
Why must it be written this way? Because boost::asio::steady_timer does not have a simple way to default-construct it first and then assign a value. It needs to know which io_context it belongs to at construction time.
Member function binding description
This sentence:
timer_.async_wait(std::bind(&Printer::on_timer,
this,
std::placeholders::_1));
The meaning is:
定时器到期后,调用 this->on_timer(ec)。
Why write &Printer::on_timer?
Because on_timer is a member function, not a regular global function. Member functions must depend on an object to be called.
Why pass this?
Because this represents the current Printer object.
Common Pitfalls
Do not write as:
std::bind(on_timer, std::placeholders::_1)
Because on_timer is a member function, not a regular function.
Also do not miss this:
std::bind(&Printer::on_timer, std::placeholders::_1)
This way, I don't know which object's on_timer() to call.
Example 6: Writing Two Timers in a Class
program objective
Maintain two timers simultaneously in a class:
timer1_execute after 1 second;timer2_execute after 3 seconds;- Use this example to clearly see that "two asynchronous tasks are not equivalent to two threads."
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
class TwoTimers
{
public:
explicit TwoTimers(boost::asio::io_context& io)
: timer1_(io, std::chrono::seconds(1)),
timer2_(io, std::chrono::seconds(3))
{
std::cout << "TwoTimers 构造:注册 timer1 和 timer2" << std::endl;
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer1_.async_wait(std::bind(&TwoTimers::on_timer1,
this,
std::placeholders::_1));
timer2_.async_wait(std::bind(&TwoTimers::on_timer2,
this,
std::placeholders::_1));
}
private:
void on_timer1(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << "timer1 取消:" << ec.message() << std::endl;
return;
}
std::cout << "timer1:1 秒到了" << std::endl;
}
void on_timer2(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << "timer2 取消:" << ec.message() << std::endl;
return;
}
std::cout << "timer2:3 秒到了" << std::endl;
}
private:
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer1_;
boost::asio::steady_timer timer2_;
};
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
TwoTimers app(io);
std::cout << "main:调用 io.run()" << std::endl;
io.run();
std::cout << "main:两个定时器都执行完,io.run() 返回" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo6_class_two_timers.cpp -o demo6_class_two_timers -std=c++17 -lboost_system -pthread
./demo6_class_two_timers
Execution output and chronological order
The program immediately outputs:
TwoTimers 构造:注册 timer1 和 timer2
main:调用 io.run()
About 1 second later:
timer1:1 秒到了
After about 3 seconds:
timer2:3 秒到了
main:两个定时器都执行完,io.run() 返回
请提供您要翻译的简体中文 Markdown 片段。
TwoTimers 构造:注册 timer1 和 timer2
main:调用 io.run()
timer1:1 秒到了
timer2:3 秒到了
main:两个定时器都执行完,io.run() 返回
Points to note for this example
timer1_ and timer2_ are two asynchronous tasks, but this example still has only one thread.
Because only the main thread called:
io.run();
So both callbacks are executed in the main thread and will not run in parallel.
Example 7: Two threads run the same io_context simultaneously.
program objective
This time, let both threads call io.run() and observe that the callback may be executed by different threads.
This example is used to understand programs like the official Timer.5:
多个线程 run 同一个 io_context
回调函数可能分配给任意一个正在 run 的线程执行
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
#include <string>
#include <thread>
void print_timer(const boost::system::error_code& ec, const std::string& name)
{
if (ec)
{
std::cout << name << " 取消:" << ec.message() << std::endl;
return;
}
std::cout << name << " 回调执行,线程 id = "
<< std::this_thread::get_id() << std::endl;
}
void run_io(boost::asio::io_context* io, const std::string& thread_name)
{
std::cout << thread_name << " 开始调用 io.run(),线程 id = "
<< std::this_thread::get_id() << std::endl;
io->run();
std::cout << thread_name << " 的 io.run() 返回" << std::endl;
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer1(io, std::chrono::seconds(1));
boost::asio::steady_timer timer2(io, std::chrono::seconds(1));
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer1.async_wait(std::bind(print_timer,
std::placeholders::_1,
std::string("timer1")));
timer2.async_wait(std::bind(print_timer,
std::placeholders::_1,
std::string("timer2")));
std::thread t1(std::bind(run_io, &io, std::string("线程1")));
std::thread t2(std::bind(run_io, &io, std::string("线程2")));
t1.join();
t2.join();
std::cout << "main:两个线程都结束" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo7_two_threads.cpp -o demo7_two_threads -std=c++17 -lboost_system -pthread
./demo7_two_threads
Execution output and chronological order
After the program starts, two threads output almost immediately:
线程1 开始调用 io.run(),线程 id = 140000000000001
线程2 开始调用 io.run(),线程 id = 140000000000002
After about 1 second, both timers expire, and the output might be similar:
timer1 回调执行,线程 id = 140000000000001
timer2 回调执行,线程 id = 140000000000002
线程1 的 io.run() 返回
线程2 的 io.run() 返回
main:两个线程都结束
It is also possible that both callbacks are executed by the same thread. Thread scheduling does not guarantee fixed behavior.
Points to note for this example
The focus of this example is:
谁调用 io.run(),谁就有可能执行回调函数。
It is not that timer1 is permanently assigned to thread 1, and timer2 is permanently assigned to thread 2.
std::thread in std::bind
This sentence:
std::thread t1(std::bind(run_io, &io, std::string("线程1")));
It means to create a thread and execute in the new thread:
run_io(&io, "线程1");
There is also no lambda used here.
Example 8: Using strand in Multithreading to Avoid Callback Concurrency
program objective
If multiple threads simultaneously run() a io_context, different callbacks may execute concurrently.
If these callbacks all modify the same member variable, a data race may occur.
strand's role is:
保证绑定到同一个 strand 上的 handler 不会并发执行。
Full code
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <functional>
#include <iostream>
#include <thread>
class StrandCounter
{
public:
explicit StrandCounter(boost::asio::io_context& io)
: strand_(boost::asio::make_strand(io)),
timer1_(io, std::chrono::seconds(1)),
timer2_(io, std::chrono::seconds(1)),
count_(0)
{
// 注册异步等待:这一行不会阻塞,回调会在定时器到期后执行。
timer1_.async_wait(
boost::asio::bind_executor(
strand_,
std::bind(&StrandCounter::on_timer,
this,
std::placeholders::_1,
1)));
timer2_.async_wait(
boost::asio::bind_executor(
strand_,
std::bind(&StrandCounter::on_timer,
this,
std::placeholders::_1,
2)));
}
private:
void on_timer(const boost::system::error_code& ec, int id)
{
if (ec)
{
std::cout << "timer" << id << " 取消:" << ec.message() << std::endl;
return;
}
++count_;
std::cout << "timer" << id << " 回调执行,count = " << count_
<< ",线程 id = " << std::this_thread::get_id() << std::endl;
}
private:
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
// 创建定时器,并设置到期时间。
boost::asio::steady_timer timer1_;
boost::asio::steady_timer timer2_;
int count_;
};
void run_io(boost::asio::io_context* io, const std::string& name)
{
std::cout << name << " 开始 run,线程 id = "
<< std::this_thread::get_id() << std::endl;
io->run();
std::cout << name << " run 返回" << std::endl;
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
// io_context 是 Asio 的事件循环对象,异步任务需要靠它调度。
boost::asio::io_context io;
StrandCounter counter(io);
std::thread t1(std::bind(run_io, &io, std::string("线程1")));
std::thread t2(std::bind(run_io, &io, std::string("线程2")));
t1.join();
t2.join();
std::cout << "main:结束" << std::endl;
return 0;
}
运行结果:见下方“运行输出与时间顺序”;如果示例涉及定时器、线程、网络或外部设备,具体时间和顺序可能会随环境略有变化。
Compile and run
g++ demo8_strand.cpp -o demo8_strand -std=c++17 -lboost_system -pthread
./demo8_strand
Execution output and chronological order
After the program starts, two threads start run():
线程1 开始 run,线程 id = 140000000000001
线程2 开始 run,线程 id = 140000000000002
After about 1 second, two timers expire:
timer1 回调执行,count = 1,线程 id = 140000000000001
timer2 回调执行,count = 2,线程 id = 140000000000002
线程1 run 返回
线程2 run 返回
main:结束
The order of the thread id and timer is not fixed, but count will not have the concurrency issue of two callbacks modifying it simultaneously.
Points to note for this example
strand does not force all callbacks to be bound to the same thread.
strand ensures that these callbacks "do not execute simultaneously."
In other words, it could be:
timer1 在线程1执行
timer2 在线程2执行
But it will not appear:
timer1 和 timer2 同时进入 on_timer()
bind_executor Description
I see you've indicated "这段:" but didn't include the Chinese text to translate. Please provide the Chinese Markdown fragment you'd like me to translate into natural American English.
boost::asio::bind_executor(strand_, handler)
Function: Bind the handler to the executor strand_.
以后 handler 执行时,会遵守这个 strand 的串行化规则。
Section Summary
You should now remember:
timer.wait()is synchronous blocking.timer.async_wait()registers an asynchronous task and does not block.io.run()is the entry point for the event loop.- A thread
run(), callbacks are executed sequentially within this thread. - Multiple threads
run(), callbacks may be executed by different threads. - When multiple threads share data, use
strandto avoid concurrent callbacks. - The standard syntax for binding a member function in a class is:
std::bind(&ClassName::member_function,
this,
std::placeholders::_1,
std::placeholders::_2)