2013-05-27 85 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