Qt多线程启动线程错误

时间:2014-01-10 10:12:28

标签: c++ multithreading qt qthread qobject

我遇到Qt多线程问题。我有一个我想要的课程

//protdata.cpp

class ProtData : public QObject
{
   Q_OBJECT
   private:
      QList<ProtDataInputHandler *> _inputs;
   public:
      ProtData();
      void addInput();
      ....
};

void ProtData::addInput(QIODevice *input, bool network_order)
{
   _inputs.append(new ProtDataInputHandler());
}

我有另一个类display.cpp,其中我使用moveToThread()将protdata对象实例化为线程;

//display.cpp
...
QThread* newThread = new QThread();
_protdata->moveToThread(newThread);
newThread->start();
...

在某些时候,在display.cpp中:

//display.cpp
....
_protdata->addInput();

当我执行addInput方法时,我收到以下错误:

  

QObject:无法为不同线程中的父级创建子级。   (Parent是ProtData(0x19bba50),父线程是QThread(0x19b3c18),当前线程是QThread(0x1f08930)

出了什么问题?我还必须将ProtDataInputHandler类移动到newThread中?怎么样?

由于

3 个答案:

答案 0 :(得分:1)

只能在procdata.cpp中调用AddInput。 如果将其定义为插槽,则可以使用信号调用函数:

// display.h

signals :

void addInputSignal();

// display.cpp
QObject::connect(this,  SIGNAL(addInputSignal()), newThread,  SLOT(addInput()));
// ...
emit addInputSignal(); 

// protdata.h

public slots:

void addInput();

答案 1 :(得分:0)

尝试将您的功能标记为Q_INVOKABLE

Q_INVOKABLE void addInput();

现在,您可以使用QMetaObject::invokeMethod进行跨线程方法调用。移动到另一个线程不会影响您直接进行的调用,但它会影响事件和信号调用,例如:

QMetaObject::invokeMethod(_procdata, "addInput", Qt::AutoConnection);

要传递参数,您需要向QMetaObject::invokeMethod添加其他参数,通常使用Q_ARG macro

答案 2 :(得分:0)

您的问题是代码中的这一行:

_inputs.append(new ProtDataInputHandler());
当你的ProtData在主线程中被实例化时,在主线程中创建了

_inputs

但是,在将ProtData QObject子类移动到另一个线程之后,调用addInput()对此进行操作。

最好的解决方案是在Qt中使用signal-slot mechanism

基本上,你会definte ProtData类中的一个插槽以及一个信号。您将从addInput中发出信号,并且相应的插槽将由Qt事件循环排队等待执行。

然后,您将在ProtData构造函数中建立信号和插槽之间的连接。

将所有这些理论付诸实践,您可以按如下方式修改代码:

//protdata.cpp

class ProtData : public QObject
{
   Q_OBJECT
   private:
      QList<ProtDataInputHandler *> _inputs;
   public:
      explicit ProtData(QObject *parent = 0);
      void addInput();
   public signals:
       void appendInput();
   public slots:
       void handleAppendInput();
      ....
};

ProtData::ProtData(QObject *parent)
    : QObject(parent)
{
    ...
    connect(this, SIGNAL(appendInput()), SLOT(handleAppendInput()));
    ...
}

void ProtData::handleAppendInput()
{
   _inputs.append(new ProtDataInputHandler());
}

void ProtData::addInput(QIODevice *input, bool network_order)
{
    emit appendInput();
}

请注意,我还修复了代码中的其他问题:

  • 我使你的构造函数显式化,因为它应该是由于使用C ++ 11进行统一初始化而已。

  • 你忘了有一个分配给基类的QObject父参数,所以我修改了它,同时在未明确指定的情况下具有默认的“无父”值。