qtmqtt 在子线程中使用

要实现在子线程中使用qtmqtt的客户端来发送和接收消息

问题:

在主线程创建一个客户端,子线程使用主线程创建的客户端,会无法通信的

//  发布线程2,共用主线程的客户端,会出现报错:QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
QThread* thread2 = new QThread();
Publish* publish = new Publish(m_client);  // m_client 对象是在主线程创建的,
publish->moveToThread(thread2);

原因: 在主线程创建的 m_client 无法在子线程中使用,只能在创建的线程中使用

解决:

参考:https://forum.qt.io/topic/109138/qmqttclient-connection-not-made-from-another-thread/9

核心思路:要在子线程中创建 客户端 QMqttClient *m_client
示例代码:

  • publish.h
#ifndef PUBLISH_H
#define PUBLISH_H

#include <QObject>
#include "QtMqtt/qmqttclient.h"

class Publish :public QObject
{
    Q_OBJECT
public:
    Publish(QObject *parent);
    Publish();
public slots:
    void messagePublish();
    void init();
    void topicSubscribe();
    void printReceiveMsg();
private:
	QMqttClient *m_client;
    QString message;
};

#endif // PUBLISH_H
  • publish.cpp
#include "publish.h"
#include <QThread>

// 创建时就创建线程
Publish::Publish(QObject *parent): QObject(parent)
{
    m_client = new QMqttClient();
    m_client->setHostname("127.0.0.1");
    m_client->setPort(1883);
    m_client->connectToHost();

    message = "main thread message!";

}

// 初始化客户端
void Publish::init()
{
    m_client = new QMqttClient();
    m_client->setHostname("127.0.0.1");
    m_client->setPort(1883);
    m_client->connectToHost();

    message = "init message!";
}

// 这个空的用来创建对象,放到QThread中
Publish::Publish()
{

}

// 发布消息
void Publish::messagePublish()
{
    qDebug() << "publishThread run : m_client state: " << m_client->state() << " (thread: " << QThread::currentThreadId() << " )";
    QString topic = "qtmqtt/topic1";
    if (m_client->publish(topic, message.toUtf8()) == -1)
    {
        qDebug() << "publish : Could not publish message" << " (thread: " << QThread::currentThreadId() << " )";
    }else{
        qDebug() << "publish ok!";
    }
}

// 订阅主题
void Publish::topicSubscribe()
{
    qDebug() << "publishThread run : m_client state: " << m_client->state() << " (thread: " << QThread::currentThreadId() << " )";
    QString topic = "qtmqtt/topic1";

    auto subscription = m_client->subscribe(topic);

    if (!subscription) {
        qDebug() << QLatin1String("Could not subscribe. Is there a valid connection?");
        return;
    }else{
        qDebug() << "subcribe ok! " << " (thread: " << QThread::currentThreadId() << " )";
    }

}

// 接收到消息,就打印出来
void Publish::printReceiveMsg()
{
    connect(m_client, &QMqttClient::messageReceived, this,
            [this](const QByteArray &message, const QMqttTopicName &topic)
    {
        const QString content = QDateTime::currentDateTime().toString()
                    + QLatin1String(" Received Topic: ")
                    + topic.name()
                    + QLatin1String(" Message: ")
                    + message
                    + QLatin1Char('\n');
        qDebug() << content << " (thread: " << QThread::currentThreadId() << " )";
    });

}
  • 使用 mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << "main thread: " << QThread::currentThreadId() << " )";

    Publish * publish = new Publish(this);
    connect(ui->pushButton ,&QPushButton::clicked,publish,&Publish::messagePublish);


    // 子线程创建客户端
    QThread * thread = new QThread;
    Publish *publishClient =  new Publish(); // 创建时不连接线程,
    publishClient->moveToThread(thread);
    connect(thread, &QThread::started, publishClient, &Publish::init);  // init连接线程,在子线程里创建客户端,并连接进行连接客户端,
    thread->start();

    connect(ui->publishButton_2_start,&QPushButton::clicked,publishClient,&Publish::messagePublish); // 子线程发布消息
    connect(ui->publishButton2_subscribe,&QPushButton::clicked,publishClient,&Publish::topicSubscribe); // 子线订阅消息
    connect(ui->publishButton2_receive,&QPushButton::clicked,publishClient,&Publish::printReceiveMsg);  // 子线程接收数据



	// 子线程定时 2000ms发送一次消息
    QTimer* timer = new QTimer(this);
    //  不能使用lambda表达式
//    QObject::connect(timer, &QTimer::timeout, [publishClient]() {
//        publishClient->messagePublish();
//        qDebug() << "Thread timer " <<QThread::currentThread();});
    connect(timer,&QTimer::timeout,publishClient,&Publish::messagePublish);
//    timer->setSingleShot(true); //设置为true之后,就会只触发一次
    timer->start(2000);


}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值