我目前正在尝试理解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);}
};
基本上,worker每隔一段时间就会显示一个 value
成员,并且有一个带有修改值的函数的插槽 .
当调用 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()
的循环?那么对插槽的调用到底在哪里(排队,丢弃,其他)?
我找不到更多关于信号/插槽机制如何与线程一起工作的信息(我只找到了this thread,它解释了哪个线程的调用堆栈对插槽的调用结束了,但答案中提供的链接似乎已过时且导致到Qt 5家) .
总结一下问题:
-
Why does the call to the slot that modifies the value does nothing ?
-
Is it possible to make this work (adding thread-safety wherever necessary) and how ?
1 回答
信号和插槽如何与线程一起工作有多种模式(你绝对必须使用
QThread
来实现它们!) . 这些内容记录在手册中:http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads代码中的错误是永远不会调用Qt事件循环(因为
doWork
永远不会返回) . 对于重复调用,您应该在该线程中使用计时器 . 或者(不是推荐的解决方案),您可以在无限循环中调用processEvents
.