2013-04-18 43 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插槽所示。

似乎做的伎俩,但总体来说不完全没有错误。

相关问题