2013-04-18 77 views
0

我已經看到QThread的許多帖子和文章,並在QThreads之間移動QObjects,但唉,它仍然讓我頭疼。這是我想要採取的模式:我不知道爲什麼我的QThread模式阻塞

#include "connectionthread.h" 
#include <cassert> 

ConnectionThread::ConnectionThread(ConnectionPtr const &connectionPtr) : 
           worker(NULL), 
           m_connectionPtr(connectionPtr) 
{ 
    connect(this, SIGNAL(executeSignal()), this, SLOT(loginProcess())); 
} 

void 
ConnectionThread::start() 
{ 
    if(worker) { 
     if(worker->isRunning()) { 
      worker->quit(); 
     } 
     delete worker; 
    } 
    worker = new QThread; 
    connect(worker, SIGNAL(started()), this, SLOT(run())); 
    worker->start(); 
} 

void 
ConnectionThread::run() 
{ 
    emit executeSignal(); 
} 

void 
ConnectionThread::loginProcess() 
{ 
    m_connectionPtr->Connect(); 
} 

現在的這個實例在主界面線程被創建,但當loginProcess最終調用,它阻止,直到完成這會導致我的應用程序的GUI掛起。請注意,如果我把邏輯代碼直接進入運行功能沒有區別觀察和省略信號像如下: -

void 
ConnectionThread::run() 
{ 
    m_connectionPtr->Connect(); 
} 

所以我認爲我需要移動「這個」的主題命名爲工人,是這樣的:

void 
ConnectionThread::start() 
{ 
    if(worker) { 
     if(worker->isRunning()) { 
      worker->quit(); 
     } 
     delete worker; 
    } 
    worker = new QThread; 
    this->moveToThread(worker); 
    connect(worker, SIGNAL(started()), this, SLOT(run())); 
    worker->start(); 
} 

,但是這給了我

QObject: Cannot create children for a parent that is in a different thread. 

我不知道這是爲什麼然而,由於ConnectionThread的實例被創建的情況和它的啓動函數被調用來自另一個線程。我們稱之爲其他線程GuiThread。這意味着GuiThread具有控制權,因此應該能夠將ConnectionThread實例的所有權轉移給工作線程。

最後一個可能性,我還沒有充分挖掘卻又是移動m_connectionPtr的工作線程的可能性..

在上面的圖案,我怎麼可能會提高它,通常我怎麼能防止任何想法它阻止?

+0

連接線程是否從任何東西派生? ConnectionPtr是否是您希望在另一個線程中執行的作業的類? Againg,是conncetionPtr派生自任何東西從您發佈的示例中,它不是很清楚... –

+0

我認爲這一點至關重要的是,如果實際上ConnectionThread對象不應該移動到單獨的線程。我看不到你想要委派給工人的行爲。現在我沒有看到工人正在發生什麼事情。 – Adrian

+0

ConnectionThread從QObject派生。並且也從QObject派生的ConnectionPtr完成了我想在另一個線程中執行的工作。 –

回答

0

編輯1:以下是我提出的解決方案,但按預期的方式完成的()信號也決不會被工作人員發出

EDIT 2不實際工作:固定觸發成品信號,但我仍然無法將m_connectionPtr移回moveConnectionPtrBack中的主線程。 (0x102900380)不能移動到目標線程(0x102900380)「

所以,我想我已經想出了該怎麼做:解決方案似乎是對ConnectionPtr的螺紋所有權轉移給工作線程:

#include "connectionthread.h" 

ConnectionThread::ConnectionThread(ConnectionPtr const &connectionPtr) : 
           worker(NULL), 
           m_connectionPtr(connectionPtr) 
{ 
    // EDIT 2 added bit -- m_connectionPtr sends signal when work finished 
    connect(m_connectionPtr.data(), 
      SIGNAL(connectFinishedSignal()), this, SLOT(quitThread())); 
} 

void 
ConnectionThread::start() 
{ 
    if(worker) { 
     if(worker->isRunning()) { 
      worker->quit(); 
     } 
     delete worker; 
    } 
    worker = new QThread; 
    m_connectionPtr->moveToThread(worker); 
    connect(worker, SIGNAL(started()), m_connectionPtr.data(), SLOT(Connect())); 
    connect(worker, SIGNAL(finished()), this, SLOT(moveConnectionPtrBack())); 
    worker->start(); 
} 

void 
ConnectionThread::moveConnectionPtrBack() 
{ 
    // this call failing still 
    m_connectionPtr->moveToThread(QApplication::instance()->thread()); 
} 

// EDIT 2 added bit; quitting causes worker to send finished signal() which causes 
// correct triggering of moveConnectionPtrBack() function 
void 
ConnectionThread::quitThread() 
{ 
    worker->quit(); 
} 

(注m_connectionPtr是一個共享的ptr,其本身是從一個QObject衍生但沒有父一個「連接」;同樣ConnectionThread導出從一個QObject,但再次,沒有父母)。

由於m_connectionPtr在將來也會被其他線程使用,我還必須將它移回到主線程,如moveConnectionPtrBack插槽所示。

似乎做的伎倆,但總體來說不完全沒有錯誤。

相關問題