2013-08-29 78 views
2

我想了解信號/插槽如何在GUI程序中工作。例如,如果主程序中的一個插槽獲取信號,它是否會創建另一個線程來處理該插槽?信號是否創建新線程?

mainwindow.h

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

public slots: 
    void finished_result(int); 

private: 
    Ui::MainWindow *ui; 
    QThread* thread; 
    Worker* worker; 

private slots: 
    void run_click(); 
}; 

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent),ui(new Ui::MainWindow){ 
    ui->setupUi(this); 
} 

MainWindow::~MainWindow(){ 
    delete ui; 
} 

void MainWindow::run_click(){ 
    thread = new QThread; 
    Worker* worker = new Worker(); 
    worker->moveToThread(thread); 
    connect(worker,SIGNAL(task_finished(int)),this,SLOT(finished_result(int))); 
    // all other necessary signal/slot connections 
    thread->start(); 

    // do more stuff 
} 

void MainWindow::finished_result(int x){ 
    // do some stuff 
} 

在一個程序,這樣,說「做更多的東西」需要一段時間來處理和工人之前完成工作run_click()退貨。所以當task_finished(int)發射時,run_click()仍然會運行。請問finished_result(int)立即啓動還是等待run_click()完成?請問finished_result(int)run_click()在一個新的線程中啓動?

我的特別問題是我在我的「做更多的東西」持有該線程一段時間不相關QWaitCondition。我希望我的finished_result(int)繼續前進,無需等待run_click()完成。任何想法如何繼續?我是否需要在新線程中向另一名工作人員「做更多的事情」?

+0

是否可以移動「做更多的東西」到它自己的工作線程?這樣,'QWaitCondition'仍然會暫停它,直到它開始工作,但它將允許主線程立即返回到事件循環。 – RobbieE

回答

3

不,信號永遠不會創建新線程。

在你的情況下,run_click()finished_result(int x)將在同一個線程,並按此順序執行。當信號task_finished(int)從您的工作線程發出的,它會被轉移,等待你的主線程隊列,等待run_click()完成,因此返回到事件循環。只有finished_result(int x)將被調用。

這被稱爲「排隊連接」,是在不同線程間使用信號和時隙時的默認行爲。有關詳細信息,請參閱文檔Threads and QObjects,尤其是Signals and Slots Across Threads

從鮑里斯
1

很好的回答(+1)

我只想補充關於第二個問題,你想finished_result(),而無需等待run_click(待處理的),那麼你就需要將它放入另一個線程(並把它連接起來),如果你想讓它「安全地」運行。

你可能會讀到Qt確實允許你強制連接成爲一個「DirectConnection」,一旦接收到信號,這個信號就被處理,這是相同線程內的信號的默認值,但是要在線程中執行此操作是非常危險的,所以不要被這種選擇所誘惑!

可能有第三種選擇來暫停當前事件並找到事件隊列中的下一個項目..但我不確定這一點,我以爲我讀了這樣的東西,但後來找不到它...也許有人可以回答那部分? (我會看看如果我能找到這個)。

+0

+1我完全同意前兩段。 (並且意識到我完全跳過了XD這個問題的一部分)。我從來沒有聽說過你在最後一部分談論什麼,但即使這是可能的,與其他線程一起看起來仍然是一個更好的方法。 – Boris

+0

@Boris是的,我沒有發現任何關於「選項3」的事情,我想這可能只存在於我的腦海! ...我知道你可以直接用事件隊列做某些事情,但要有效地「切換」(把你正在做的事放在隊列中,並開始下一個項目)....可能不是:( –

+0

無論如何,這是很好的提及,我從來沒有和自己的隊伍一起打過球,我認爲我很快就不會有實際的需求,但它看起來很有趣,所以我可能會在閒暇時嘗試打這場比賽:-P – Boris