0

I have a problem, I'm trying to synchronize some QThreads with the main GUI and I have not good results!

I have a main window (I have some windows but the problem seems to be the same) that will interact with two kind of devices: A serial port (using qserialport) and a camera (using opencv).

In order to make them work, I need to use parallel processing. I made three QThreads: * One to make synchronizations between devices and main window (principally, for complex operations) * One to manage the serial port (using libqt5serialport) * One for manage vision algorithms.

In order to communicate between these process, first, I'm trying to use signals and slots (also, probably I will use shared memory, mutex or a combination of them).

When I try to connect signals from my Serial Port object to slots in my QThread, the slot is not called and I receive a warning (in execution time): QObject: Cannot create children for a parent that is in a different thread.

The code is very simple, the code of Vision is not implemented at this code, I need to be sure that I can communicate the procecess probably is very conceptual, when I try to stand, i cannot.

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: Another test: I can connect to readyRead with this QThread (signal emitted in my method, this signal worked for me without QThreads), but not to my own signal in CommunicationSerial, that has an object called serial and type QSerialPort. connect(miEstado->miCommunication->serial, SIGNAL(readyRead()),\ &me, SLOT(datosPorLeer())); // See note 5

Returned Id's (QThread::CurrentThreadId())


main process id: 0x7f9ae9b2eac0 (main window, QObject)

Method run() of Action Id: 0x7f9ac382b700 (QThread)

Method run() of ActionCommunication Id: 0x7f9ac302a700 (Another QThread)

Id inside my QSerialPort based object (CommunicationSerial): 0x7f9ac302a700, printed on CommunicationSerial constructor

Id of slot ActionCommunication::Conectar(): 0x7f9ac302a700 (will be the same where my program fails)

Note1: I have translated some part of my code in order to make more easy to understand. Sorry if I have made a mistake, I think that the problem is very clear and I cannot understand what is happening. QSerialPort is running with the same id as ActionCommunication, and I cannot understand the warning.

Note2: The problem appears when I will receive information from Serial Port (CommunicationSerial), I connect without problems, and when the device send some information, the slot readyData is not executed. If I use this code without QThread (directly from the main window code) I have not problems.

Note3: When I will receive data, the warning appears (QObject: Cannot create children for a parent that is in a different thread), also I receive this second message: (Parent is QSerialPort(0x7f6ac4002c80), parent's thread is AccionComunicacion(0x1dbe810), current thread is QThread(0x1d4be30) Note that they are pointers and probably them has changed from the last time.

Also, if I try to use CommunicationSerial->moveToThread(&me) or CommunicationSerial->moveToThread(this) in run() method of ActionCommunication, the warning is the same.

Note 4: Also, I have tried CommunicationSerial to inherit QObject (It inherited QSerialPort) and adding an QSerialPort object inside CommunicationSerial and I have added the methods that I need to do this. The results are the same.

Note 5: I have added a connection to readyRead() in CommunicationSerial->serial, that is, to QSerialPort object, and it works normally, but I continue with the same problem to connect readyStatus in CommunicationSerial (my own signal) receiving the mentioned error.

** I continue sending data, but I cannot receive readyStatus signal. (Parent is QSerialPort(0x7f6ac4002c80), parent's thread is AccionComunicacion(0x1dbe810), current thread is QThread(0x1d4be30) Note that they are pointers and probably them has changed from the last time.

Draken
  • 3,134
  • 13
  • 34
  • 54
Diego
  • 35
  • 7
  • 1
    http://stackoverflow.com/questions/11033971/qt-thread-with-movetothread – Alexander V Oct 24 '16 at 04:25
  • Hello Alexander! Thanks for your repply! I continue with the problem, I cannot understand the error, I tried to move the QSerialPort objecto to inside CommunicationSerial and make CommunicationSerial QObject (instead of QSerialPort) and moving CommunicationSerial to the QThread but i get the same results. Also, I do the same moovingo to &me, the only change is the moment when I receive the error from QT, but the error is the same. I go to edit my post adding a note (Note3). – Diego Oct 24 '16 at 17:28

0 Answers0