我遇到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中?怎么样?
由于
答案 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父参数,所以我修改了它,同时在未明确指定的情况下具有默认的“无父”值。