mardi 29 octobre 2019

Inherited from qthread class doesn't work with queued connection

I wrote simple class of smart container for producer consumer approach. Data in container are added by posix thread via callBack, after it my thread is awakening and parse all received messages. The main problem is that my thread calling method of other QObject subclass where signal emmiting are exists, the main problem that after signal emmiting, slot doesn't receive a message only direct connection are work.

   #ifndef SHAREDCONTAINEREXTERNAL_H
#define SHAREDCONTAINEREXTERNAL_H
#include <QThread>
#include <QWaitCondition>
#include <QMutex>
#include <QQueue>
#include <QObject>

class Device;

class SharedContainerExternal : public QThread
{
    Q_OBJECT
public:
    explicit SharedContainerExternal(QObject* parent = nullptr);
    ~SharedContainerExternal()override;
    void setRawMessage(const QJsonObject& _message);
    void setConsumerObject(Device* _consumer);
    void consumerRead();

protected:
    void run() override;

private:
    QMutex mtx;
    QWaitCondition cv;
    QQueue<QJsonObject> messages;
    Device* consumer;
    bool canAccomplish;
};


#include "sharedcontainerexternal.h"
#include "device.h"

SharedContainerExternal::SharedContainerExternal(QObject* parent) : QThread (parent)
{
    canAccomplish = false;
}

SharedContainerExternal::~SharedContainerExternal()
{
    mtx.lock();
    canAccomplish = true;
    cv.notify_all();
    mtx.unlock();
    wait();
}

void SharedContainerExternal::setRawMessage(const QJsonObject &_message)
{
    mtx.lock();
    messages.push_back(_message);
    cv.wakeAll();
    mtx.unlock();
}

void SharedContainerExternal::run()
{
    while(!canAccomplish){
        mtx.lock();
        if(messages.isEmpty() && !canAccomplish)
            cv.wait(&mtx);
        consumerRead();
        mtx.unlock();
    }
}

void SharedContainerExternal::setConsumerObject(Device *_consumer)
{
    consumer = _consumer;
}

void SharedContainerExternal::consumerRead()
{
    while(!messages.isEmpty()){
        consumer->getDriverMessage(messages.front());
        messages.pop_front();
    }
}

So after in driver class I have emit a signal.

void Device::getDriverMessage(const QJsonObject& _message)
{
    emit sendCallBackMessage(_message);
}

And in mainwindow class I have a connect, but signal doesn't received via slot, device is a field of class mainwindow.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    fields[LinkAgentType] = TypeOfConnection::EXTERNAL;
    fields[PathToDriver] = "C:/Users/user/Desktop/RouterCpp/RouterCore/build-Driver101-104-Desktop_Qt_5_13_0_MinGW_32_bit-Debug/debug/Driver101-104";
    fields[IpAddr] = "127.0.0.1";
    fields[Port] = 2404;
    fields[TypeOfDevice] = TypeOfDevice::External;
    fields[TypeOfMessage] = TypeOfMessage::Service;
    fields[ConnectionState] = ConnectState::On;

    /*Prepare parameters for the jsonObject*/
    builder = new DeviceBuilder(this);
    builder->setConstructorStructure(fields);
    device = builder->getDeviceObject();
    device->setMessage(fields);

    connect(device.get(),&Device::sendCallBackMessage,
            this,&MainWindow::callBackMessageSlot,Qt::QueuedConnection);


}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::callBackMessageSlot(QJsonObject _data)
{
    qDebug()<<_data;
}

Aucun commentaire:

Enregistrer un commentaire