提升信号和插槽在不同线程中不工作(使用 boost::asio::io_service)
boost signal and slot not working in different thread (using boost::asio::io_service)
我编写了一个小测试程序来了解 boost 提供的 signal and slot
机制以及它们在不同线程中发布时的行为。我想在不同的线程中调用插槽,但我的程序的输出显示插槽没有在发出信号的不同线程中调用。
#include <iostream>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/random.hpp>
#include <boost/signals2.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/signals2/signal.hpp>
boost::signals2::signal<void (int)> randomNumberSig;
// ---------------- Thread 1 ----------------
boost::asio::io_service thread1_serv;
void handle_rnd_1(int number)
{
std::cout << "Thread1: " << boost::this_thread::get_id() << " & Number is " << number << std::endl;
}
void thread1_init(void)
{
std::cout << "Thread 1 Init" << std::endl;
boost::asio::io_service::work work (thread1_serv);
randomNumberSig.connect([] (int num) -> void {
std::cout << "Slot called from main thread" << std::endl;
thread1_serv.post(boost::bind(handle_rnd_1, num));
});
}
void thread1_loop(void)
{
}
void thread1(void)
{
thread1_init();
while (true) {
thread1_serv.run();
thread1_loop();
}
}
int main(int argc, char *argv[])
{
std::cout << "Starting the Program" << std::endl;
boost::thread t1(&thread1);
while (1) {
int num = 2;
std::cout << "Thread " << boost::this_thread::get_id() << " & Number: " << num << std::endl;
randomNumberSig(num);
boost::this_thread::sleep_for(boost::chrono::seconds(num));
}
return 0;
}
程序的输出是:
Starting the Program
Thread 7fae3a2ba3c0 & Number: 2
Thread 1 Init
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
我怀疑 io_service
的 post()
方法工作不正常,或者我在初始化 io_service
时遗漏了一些东西。
您没有正确处理 run
函数的调用。
您使用 work
来防止 run
在没有工作可做时结束。
但是你的 work
是本地的 thread1_init
所以当这个函数结束时, work
当没有要调用的处理程序时,被销毁并且 io_service::run
退出。
run
完成后,io_service
标记为停止,需要调用restart
之前
调用 run
(作为后续调用)。
如果您不在不处理任何处理程序的情况下立即调用 restart
、run
returns - 这就是您看不到它们的原因。
所以第一个解决方案是创建 work
其生命周期与 io_service
相同(只需使用全局变量 - 丑陋):
boost::asio::io_service thread1_serv;
boost::asio::io_service::work work(thread1_serv);
另一种解决方案,不要使用work
,只需在run
之前调用restart
:
thread1_init();
while (true) {
thread1_serv.restart();
thread1_serv.run();
thread1_loop();
}
我编写了一个小测试程序来了解 boost 提供的 signal and slot
机制以及它们在不同线程中发布时的行为。我想在不同的线程中调用插槽,但我的程序的输出显示插槽没有在发出信号的不同线程中调用。
#include <iostream>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/random.hpp>
#include <boost/signals2.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/signals2/signal.hpp>
boost::signals2::signal<void (int)> randomNumberSig;
// ---------------- Thread 1 ----------------
boost::asio::io_service thread1_serv;
void handle_rnd_1(int number)
{
std::cout << "Thread1: " << boost::this_thread::get_id() << " & Number is " << number << std::endl;
}
void thread1_init(void)
{
std::cout << "Thread 1 Init" << std::endl;
boost::asio::io_service::work work (thread1_serv);
randomNumberSig.connect([] (int num) -> void {
std::cout << "Slot called from main thread" << std::endl;
thread1_serv.post(boost::bind(handle_rnd_1, num));
});
}
void thread1_loop(void)
{
}
void thread1(void)
{
thread1_init();
while (true) {
thread1_serv.run();
thread1_loop();
}
}
int main(int argc, char *argv[])
{
std::cout << "Starting the Program" << std::endl;
boost::thread t1(&thread1);
while (1) {
int num = 2;
std::cout << "Thread " << boost::this_thread::get_id() << " & Number: " << num << std::endl;
randomNumberSig(num);
boost::this_thread::sleep_for(boost::chrono::seconds(num));
}
return 0;
}
程序的输出是:
Starting the Program
Thread 7fae3a2ba3c0 & Number: 2
Thread 1 Init
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
我怀疑 io_service
的 post()
方法工作不正常,或者我在初始化 io_service
时遗漏了一些东西。
您没有正确处理 run
函数的调用。
您使用 work
来防止 run
在没有工作可做时结束。
但是你的 work
是本地的 thread1_init
所以当这个函数结束时, work
当没有要调用的处理程序时,被销毁并且 io_service::run
退出。
run
完成后,io_service
标记为停止,需要调用restart
之前
调用 run
(作为后续调用)。
如果您不在不处理任何处理程序的情况下立即调用 restart
、run
returns - 这就是您看不到它们的原因。
所以第一个解决方案是创建 work
其生命周期与 io_service
相同(只需使用全局变量 - 丑陋):
boost::asio::io_service thread1_serv;
boost::asio::io_service::work work(thread1_serv);
另一种解决方案,不要使用work
,只需在run
之前调用restart
:
thread1_init();
while (true) {
thread1_serv.restart();
thread1_serv.run();
thread1_loop();
}