我遇到了问题,我正在尝试将某些QThread
与主GUI同步,但效果不佳!
我有一个主窗口(我有一些窗口,但问题似乎是相同的),它将与两种设备交互:一个串口(使用qserialport)和一个摄像头(使用opencv)。
为了使它们工作,我需要使用并行处理。我做了三个QThreads: *一个用于在设备和主窗口之间进行同步(主要用于复杂操作) *一个管理串口(使用libqt5serialport) *一个用于管理视觉算法。
为了在这些过程之间进行通信,首先,我正在尝试使用信号和插槽(也许,我可能会使用共享内存,互斥或它们的组合)。
当我尝试将来自我的串行端口对象的信号连接到QThread
中的插槽时,未调用插槽并且我收到警告(执行时间):
QObject
:无法为位于其他线程中的父级创建子级。
代码非常简单,Vision的代码没有在这段代码中实现,我需要确定我可以沟通的过程可能是非常概念性的,当我试图站立时,我不能。
action.cpp:
#include "action.h"
Action::Action(QObject *parent, estadoGeneral *Estado)
: QThread(parent)
{
myEstado = Estado;
//Create new QThreads, one for camera aon other for serial port
tCommunication = new ActionCommunication(this, myEstado);
tVision = new ActionVision(this, myEstado);
}
Action::~Action()
{
//TODO: free memory, stop, etc.
}
void Action::run()
{
cout << "run() Action, id: " << QThread::currentThreadId() << endl;
Action me;
QTimer myTimer;
//Esto si funciona
// connect(myEstado->myCommunication, &SerialCommunication::readyRead, &myAction, &Action::readData);
#ifdef _ALIVE
//Signal works
connect(&myTimer, &QTimer::timeout, &me, &Action::estaVivo);
myTimer.start(10000);
#endif
tCommunication->start();
//tVision->start();
exec();
}
//Signal to connect
void Action::conectarSerie()
{
cout << "Petición de conectar enviada por id " << QThread::currentThreadId() << endl;
emyt sConectar();
}
void Action::enviarComando(int Comando)
{
cout << "Petición de comando " << QThread::currentThreadId() << endl;
emyt sEnviarComando1(Comando);
}
void Action::enviarComando(int Comando, int arg1)
{
cout << "Petición de comando " << QThread::currentThreadId() << endl;
emyt sEnviarComando2(Comando, arg1);
}
//Just a test
void Action::estaVivo()
{
cout << "Action está vivo, signal id: " << this->currentThreadId() << endl;
}
//QThread to manage serial port
ActionCommunication::ActionCommunication(QObject *parent, estadoGeneral *Estado)
: QThread(parent)
{
mainParent = parent;
myEstado = Estado;
}
ActionCommunication::~ActionCommunication()
{
//TODO
}
void ActionCommunication::run()
{
cout << "run() ActionCommunication, id: " << QThread::currentThreadId() << endl;
myEstado->myCommunication = new SerialCommunication();
ActionCommunication me;
me.myEstado = myEstado;
//Connect the signals
{
connect(mainParent, SIGNAL(sConectar()), &me, SLOT(conectar()));
connect(mainParent, SIGNAL(sEnviarComando1(int)), &me, SLOT(EnviarComando1(int)));
connect(mainParent, SIGNAL(sEnviarComando2(int, int)), &me, SLOT(EnviarComando2(int, int)));
//Here is the problem
//*******************
connect(myEstado->myCommunication, SIGNAL(readyStatus(int,int,int,int,int)),\
&me, SLOT(readyStatus(int,int,int,int,int)));
}
exec();
}
//Try to communicate, it works
void ActionCommunication::conectar()
{
cout << "connect - ActionCommunication id " << QThread::currentThreadId();
myEstado->myCommunication->configurePort(myEstado->mysSettings);
if(myEstado->myCommunication->openSerialPort()) emyt sConectado(true);
else emyt sConectado(false);
}
//Send commands to serial port, it works
void ActionCommunication::EnviarComando1(int comando)
{
cout << "Comando en ActionCommunication id " << QThread::currentThreadId();
//nComando is an enum, I cast in order to send via signal
myEstado->myCommunication->enviarComando((nComando) comando);
}
void ActionCommunication::EnviarComando2(int comando, int arg1)
{
cout << "Comando en ActionCommunication id " << QThread::currentThreadId();
myEstado->myCommunication->enviarComando((nComando) comando,(nComando) arg1);
}
//Here is the problem, i never receive the signal sent by serialport, that is a `qserialport`
// ****************************************************************************************
// When the signal is received, I got the warning
void ActionCommunication::readyStatus(int id, int x, int y, int z, int t)
{
cout << "Id: " << id << "x" << x << "..." << endl;
}
/******************
//Not implemented, interface to operate with opencv classes.
******************/
ActionVision::ActionVision(QObject *parent, estadoGeneral *Estado)
: QThread(parent)
{
}
ActionVision::~ActionVision()
{
}
void ActionVision::run()
{
}
action.h:
#ifndef ACCION_H
#define ACCION_H
#include <QWidget>
#include <QObject>
#include <QThread>
#include "helpers.h"
#include "estadogeneral.h"
#include "vision.h"
//Here is the code that emit the signal, inherits QSerialPort
#include "comunicacionserie.h"
QT_BEGIN_NAMESPACE
class QImage;
QT_END_NAMESPACE
class ActionCommunication : public QThread
{
Q_OBJECT
public:
ActionCommunication(QObject *parent = 0, estadoGeneral *Estado=NULL);
estadoGeneral *myEstado;
~ActionCommunication();
QObject *mainParent;
CommunicationSerie *myCommunication;
public slots:
void conectar();
void EnviarComando1(int comando);
void EnviarComando2(int comando, int arg1);
// ********************* Problematic slot *******************
void readyStatus(int id, int x, int y, int z, int t);
signals:
void sConectado(bool);
protected:
void run() Q_DECL_OVERRIDE;
private:
};
class ActionVision : public QThread
{
Q_OBJECT
public:
ActionVision(QObject *parent = 0, estadoGeneral *Estado=NULL);
~ActionVision();
protected:
void run() Q_DECL_OVERRIDE;
private:
estadoGeneral *myEstado;
};
class Action : public QThread
{
Q_OBJECT
public:
Action(QObject *parent = 0, estadoGeneral *Estado=NULL);
~Action();
int irAFiducial(int nFiducial, bool esGlobal);
void estaVivo();
ActionCommunication *tCommunication;
ActionVision *tVision;
void conectarSerie();
void enviarComando(int Comando);
void enviarComando(int Comando, int arg1);
signals:
void sConectar();
void sEnviarComando1(int);
void sEnviarComando2(int, int);
protected:
void run() Q_DECL_OVERRIDE;
private:
estadoGeneral *myEstado;
};
#endif // ACCION_H
PS:
另一个测试:我可以使用此readyRead
连接到QThread
(在我的方法中发出的信号,此信号对我没有QThreads有效),但不是我在CommunicationSerial中的信号,它有一个名为serial的对象并输入QSerialPort.
connect(miEstado->miCommunication->serial, SIGNAL(readyRead()),\
&me, SLOT(datosPorLeer()));
//参见注释5
返回ID(QThread::CurrentThreadId()
)
主进程ID:0x7f9ae9b2eac0(主窗口,QObject)
Action Id的方法run():0x7f9ac382b700(QThread)
ActionCommunication Id的方法run():0x7f9ac302a700(另一个QThread)
我的基于QSerialPort的对象(CommunicationSerial)中的Id:0x7f9ac302a700,打印在CommunicationSerial构造函数
插槽ID IdCommunication :: Conectar():0x7f9ac302a700(与程序失败的情况相同)
注1:我已翻译了部分代码,以便更容易理解。对不起,如果我犯了一个错误,我认为问题非常明确,我无法理解发生了什么。 QSerialPort的运行ID与ActionCommunication相同,我无法理解警告。
注意2:当我从串行端口(CommunicationSerial
)接收信息时出现问题,我连接没有问题,当设备发送一些信息时,插槽readyData
不会被执行。如果我在没有QThread
的情况下使用此代码(直接来自主窗口代码),我没有问题。
注意3:当我收到数据时,会出现警告(QObject:无法为不同线程中的父项创建子项),我也会收到第二条消息: (Parent是QSerialPort(0x7f6ac4002c80),父线程是AccionComunicacion(0x1dbe810),当前线程是QThread(0x1d4be30) 请注意,它们是指针,可能它们从上次发生了变化。
另外,如果我尝试在CommunicationSerial->moveToThread(&me)
的{{1}}方法中使用CommunicationSerial->moveToThread(this)
或run()
,则警告是相同的。
注4:另外,我已经尝试过CommunicationSerial继承QObject(它继承了QSerialPort)并在CommunicationSerial中添加了一个QSerialPort对象,并添加了我需要的方法。结果是一样的。
注意5:我在CommunicationSerial-&gt; serial中添加了ActionCommunication
的连接,即readyRead()
对象的连接,并且它正常工作,但我继续遇到同样的问题来连接{在QSerialPort
(我自己的信号)中{1}}收到上述错误。
**我继续发送数据,但我无法收到readyStatus
信号。
(Parent是QSerialPort(0x7f6ac4002c80),父线程是AccionComunicacion(0x1dbe810),当前线程是QThread(0x1d4be30)
请注意,它们是指针,可能它们从上次发生了变化。