2013-05-27 57 views
1

我目前正在试图了解Qt中的信号和插槽如何与线程行为。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);} 
}; 

基本上,工人在一段时间显示其value构件每一次,并有一个槽与该修改值的函数。

当调用changeTheValue时,管理器的唯一目的是发出带有新值的信号,该信号映射到修改value成员的Worker中的插槽。

然后,我让我的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::modifiedValueWorker::changeValue似乎不工作?仅仅是因为线程当前正在运行doWork()的循环?对插槽的呼叫最终会在哪里结束(排队,丢弃,其他)?

我无法找到更多关于信号/插槽机制如何与线程一起工作的信息(我只找到this thread,它解释了哪个线程的调用堆栈对插槽的调用结束了,但答案中提供的链接似乎过时了,导致Qt 5回家)。

要总结的问题:

  • 为什么调用修改该值什么都不做了卡槽?
  • 是否有可能使这项工作(在必要时增加线程安全性)以及如何?
+0

我希望你有[RTFM](http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads)。 – rubenvb

+0

不幸的是,这并不能回答我的问题。我知道QObject及其子类的'线程不安全',并且信号和插槽之间的连接默认情况下适用于上下文(自动地在同一线程中的对象之间直接连接,或者在不同对象之间的排队连接线程),但感谢您的链接! – JBL

回答

3

信号和插槽如何与线程一起工作有多种模式(您绝对必须使用QThread这些工作!)。这些都记录在手册中: http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads

在你的代码中的错误是把Qt的事件循环不会被调用(如doWork永远不会返回)。对于重复调用,您应该在该线程中使用计时器。或者(不是推荐的解决方案),你可以在你的无限循环中调用processEvents

+0

那么,正如上面的评论(已经指出这个链接)所解释的那样,它不能解决我的问题(尽管这是一个有用的链接)。 – JBL

+0

它确实回答了标题中给出的问题,但是;)我只是扩展了答案,指出为什么您的示例不起作用。 – Joe

+0

是的,你是对的,我不知道如何使用作为一个标题,不会结束1公里长... +1 – JBL