我目前正在尝试了解 Qt 中的信号和插槽如何与线程一起工作。
我尝试使用以下代码运行一个小测试:
class Worker : public QObject{
Q_OBJECT
public:
Worker(int _value){value = _value;}
~Worker(){};
int value;
public slots:
void changeValue(int newValue){value = newValue;}
void doWork(){
while(1){
_sleep(500);
std::cout << "Value is " << value << std::endl;
if(value == 0)break;
}
emit finished();
}
signals:
void finished();
};
class Manager : public QObject{
Q_OBJECT
public:
Manager(){}
~Manager(){};
signals:
void modifiedValue(int value);
public:
void changeTheValue(int value){emit modifiedValue(value);}
};
基本上,workervalue
每隔一段时间就会显示它的成员,并且有一个带有修改值的函数的槽。
管理器的唯一目的是在被调用时发出具有新值的信号,该信号changeTheValue
映射到 Worker 中修改value
成员的插槽。
然后我让我的Worker
班级通过以下方式在一个线程中工作:
QThread myThread;
Worker myWorker(10);
Manager manager;
myWorker.moveToThread(&myThread);
QObject::connect(&myThread, SIGNAL(started()), &myWorker,SLOT(doWork()));
QObject::connect(&myWorker, SIGNAL(finished()), &myThread, SLOT(quit()));
QObject::connect(&myWorker, SIGNAL(finished()), &myWorker, SLOT(deleteLater()));
QObject::connect(&myThread, SIGNAL(finished()), &myThread, SLOT(deleteLater()));
QObject::connect(&manager, SIGNAL(modifiedValue(int)),
&myWorker, SLOT(changeValue(int)));
myThread.start();
for(int i = 1; i < 10 ; i++){
_sleep(1000);
manager.changeTheValue(i);
}
manager.changeTheValue(0);
但什么也没有发生。该值似乎没有改变:输出显示十几行带有Value is 10
.
我不明白的是,为什么信号/槽映射Manager::modifiedValue
和Worker::changeValue
似乎不起作用?仅仅是因为线程当前正在运行doWork()
' 循环吗?那么对插槽的调用在哪里结束(排队,丢弃,其他)?
我找不到更多关于信号/插槽机制如何与线程一起工作的更多信息(我只找到了这个线程,它解释了对插槽的调用最终在哪个线程的调用堆栈中结束,但答案中提供的链接似乎已经过时并且导致 Qt 5 主页)。
总结一下问题:
- 为什么对修改值的插槽的调用什么都不做?
- 是否有可能使这项工作(在必要时添加线程安全)以及如何?