QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread 问题解决

文章讲述了在使用Qt进行多线程编程时遇到的问题,即QSocketNotifier错误。问题源于QUdpSocket对象在主线程中创建,但其信号触发的槽函数在子线程中执行。解决方案是将QUdpSocket的初始化移动到子线程中执行,通过moveToThread和信号连接实现。
摘要由CSDN通过智能技术生成

使用Qt的多线程时,出现 QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread 的错误。通过查询资料总结如下:

  1. 创建一个子线程对象是主线程的工作.也就是说在对象在哪个线程被实例化就属于哪个线程.
  2. 利用movetothread函数可以将对象转移至另外的线程.
  3. QThread的run函数属于子线程
  4. 信号和槽 隶属于它们所在对象的线程.
  5. 使用connect之后,槽函数默认执行在槽函数所在线程,若改变connect函数的第五个参数,比如设为Qt::DirectConnection,可让槽函数在信号所在线程执行.

根据以上的结论,代码报错的原因是:

  1. QUdpSocket对象在DataReceive的构造函数中被实例化,而DataReceive的实例化是被主线程实例化的,因此QUdpSocket也属于主线程,而QUdpSocket发出的socket通知是在主线程,对应的槽函数是在子线程.

原来的代码:

#pragma once

#ifndef DataReceive_h__
#define DataReceive_h__

#include <QObject>
#include <QByteArray>
#include "common.h"

class QUdpSocket;

class DataReceive  : public QObject
{ 
	Q_OBJECT

public:
	DataReceive(QObject *parent=nullptr);
	~DataReceive();

public slots:
	void slotReadyRead();
	void doInit();

signals:
	void sigCoilData(Coils_T coils);
	void sigSensorData(Sensors_T sensors);

private:
	QByteArray _recv();

private:
	QUdpSocket* m_pUdp = nullptr;
	QByteArray _cache;
	QByteArray _packet;
	Coils_T _cache_coils;
	Sensors_T _cache_sensors;

	std::vector<int> _coils_mask{ 0,1,2,3,4,5,6,7,8,9 };
	std::vector<int> _sensors_mask{ 0,1,2,3,4,5,6,7,8,9 };
};
#endif // DataReceive_h__


DataReceive::DataReceive(QObject *parent)
	: QObject(parent)
{
	m_pUdp = new QUdpSocket;
	m_pUdp->bind(QHostAddress::LocalHost, 244);
	//接收数据
	bool isR = connect(m_pUdp, &QUdpSocket::readyRead, this, &DataReceive::slotReadyRead);
}

更改后:

void DataReceive::doInit() {
	m_pUdp = new QUdpSocket;
	m_pUdp->bind(QHostAddress::LocalHost, 244);
	//接收数据
	bool isR = connect(m_pUdp, &QUdpSocket::readyRead, this, &DataReceive::slotReadyRead);
}

将DataReceive构造函数中初始化upd的代码放到了doInit中,该函数被

    QThread* t = new QThread;
    m_dataReceive->moveToThread(t);
    bool isB = connect(t, SIGNAL(started()), m_dataReceive, SLOT(doInit()));

started信号调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值