我有一个应用程序,我需要通过不同的线程在单个方法内调用多个方法。 每个方法应该以不同的时间间隔调用。 我正在使用 boost 库以不同的时间间隔重复执行调用函数。
我的问题是,对所有这些使用单个 boost::asio::io_context 是否安全?
这里是一个示例代码,展示了代码的外观。 枚举类型和类/结构声明将是
struct TestTimerContext {
boost::asio::steady_timer timer;
NssStatsTimerContext(boost::asio::io_context& io) : timer(io) {}
};
enum MethodTypes { FIRST = 0, SECOND = 1, THIRD = 2 };
class Myclass {
public:
Myclass(boost::asio::io_context& io): io_context_(io) {}
void start_process (vector<bool> condistions, vector<uint32> intervals);
std::thread method_1_thread_;
std::thread method_2_thread_;
std::thread method_3_thread_;
private:
boost::asio::io_context io_context_;
void start_method_thread (uint32 interval, MethodTypes method_type);
void func_cb ( const boost::system::error_code& err, uint32_t interval, MethodTypes method_type);
void method1 (uint32 interval);
void method1 (uint32 interval);
void method1 (uint32 interval);
};
这将是我如何使用 boost::asio::io_context 以不同的时间间隔调用该方法。我刚刚从示例代码中删除了所有逻辑,以分享高级想法并保持简单
Myclass::start_process (vector<bool> condistions, vector<uint32> intervals) {
if (conditions[0]) {
method_1_thread_ = std::thread([&]() {
start_method_thread (intervals[0], MethodTypes::FIRST);
});
}
if (conditions[1]) {
method_2_thread_ = std::thread([&]() {
start_method_thread (intervals[1], MethodTypes::SECOND);
});
}
if (conditions[2]) {
method_3_thread_ = std::thread([&]() {
start_method_thread (intervals[2], MethodTypes::THIRD);
});
}
if (method_1_thread_.joinable()) {
method_1_thread_.join();
}
if (method_2_thread_.joinable()) {
method_2_thread_.join();
}
if (method_3_thread_.joinable()) {
method_3_thread_.join();
}
}
void Myclass:: start_method_thread (uint32 interval, MethodTypes method_type) {
std::unique_ptr<TestTimerContext> ctx;
ctx = std::make_unique<TestTimerContext>(io_context_);
auto& ctx_ref = *ctx;
if (interval ==0) {
func_cb( err, interval, method_type);
} else {
ctx_ref.timer.expires_after(std::chrono::milliseconds(interval));
ctx_ref.timer.async_wait([&](const boost::system::error_code& err) mutable {
func_cb( err, interval, method_type);
});
}
}
void Myclass::func_cb (
const boost::system::error_code& err,
uint32_t interval,
MethodTypes method_type) {
if (err) {
cout<<"cb function has an error"<<endl;
return;
}
switch (method_type) {
case MethodTypes::FIRST:
method1();
break;
case MethodTypes::SECOND:
methdo2();
break;
case MethodTypes::THIRD:
method3();
break;
default:
cout<<"method type is not supported"<<end;
return;
}
if (interval == 0) {
// do nothing
} else {
auto ctx = Arc<TestTimerContext>(io_context_);
auto& ctx_ref = *ctx;
ctx_ref.timer.expires_after(std::chrono::milliseconds(interval));
ctx_ref.timer.async_wait([&](const boost::system::error_code& err) mutable {
func_cb(err, interval, method_type);
});
}
}
void Myclass::method1 () {
cout<<"method1 is called!"<<end;
}
void Myclass::method2 (){
cout<<"method3 is called!"<<end;
}
void Myclass::method3 (){
cout<<"method3 is called!"<<end;
}
如果您可以分享您的反馈,我将不胜感激,但是是的,我的主要问题是我是否可以在所有这些线程之间共享相同的 io_context 变量?
是的,对示例中的所有计时器和线程使用单个 boost::asio::io_context 是安全的。 io_context 旨在同时处理多个异步操作,因此您可以将它用于所有计时器和线程,而不会出现任何问题。
在您的代码中,每个计时器回调 (func_cb) 都与特定的 io_context 关联,这确保回调在创建它们时使用的 io_context 上下文中执行。这使您可以安全地为所有计时器和线程使用单个 io_context。
但是,请记住,您需要确保 io_context 的寿命比使用它的所有计时器和线程都长。这通常意味着您应该适当管理 io_context 的生命周期,确保在所有计时器和线程完成其操作之前它不会被销毁。
问题
您认为在不同线程上调用 async_wait 可以获得什么好处?需要明确的是,回调不会在调用 async_wait 的线程上调用;它将在调用 io_context_.run 的任何线程上调用。异步等待
回答
在不同线程上调用 async_wait 允许您安排多个异步操作同时执行。即使回调(在本例中为 func_cb)将在调用 io_context_.run() 的线程上调用,但使用多个线程调用 async_wait 可以帮助分配工作负载并提高应用程序的响应能力。
通过使用多个线程调用async_wait,可以确保不同的计时器同时处理,而不是等待一个计时器完成后再启动下一个计时器。如果您有多个具有不同间隔的计时器,并且您希望确保它们的处理时间尽可能接近其计划时间,则这尤其有用。
总的来说,使用多个线程调用 async_wait 可以让您同时处理多个异步操作,从而帮助提高应用程序的性能和效率。