C++ QT多线程中信号槽(传递自定义数据类型) tcy

1.1.传递复杂数据类型QT内部提供一组宏:
  Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)声明关联容器元类型
  Q_DECLARE_METATYPE(Type)                           声明元类型
  Q_DECLARE_OPAQUE_POINTER(PointerType)              声明不透明的指针
  Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container) 声明顺序容器元类型
  Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer)     智能指针 
1.2.QT信号与槽连接方式:    
1)Qt::AutoConnection
	表示系统自动选择相应连接方式,如信号与槽在同一线程采用Qt::DirectConnection, 
    如信号与槽不在同一线程采用Qt::QueuedConnection的连接方式。   
2)Qt::DirectConnection
	表示一旦信号产生立即执行槽函数    
3)Qt::QueuedConnection
	表示信号产生后,将发送Event给你receiver所在线程postEvent(QEvent::MetaCall,...), 
	slot函数会在receiver所在线程的event loop中进行处理    
4)Qt::BlockingQueuedConnection
	表示信号产生后调用sendEvent(QEvent::MetaCall,...), 
	在receiver所在的线程处理完成后才会返回;只能当sender,receiver不在同一线程时才可以    
5)Qt::UniqueConnection
	表示只有它不是一个重复连接,连接才会成功。
	如果之前已经有了一个链接(相同信号连接到同一对象的同一个槽上),那么连接将会失败并将返回false   
6)Qt::AutoCompatConnection与QT3保持兼容性 
说明:
	1)对于任何QThread来说,其线程只存在于run()函数内,其它函数都不在线程内
	2)SOCKET采用Qt::BlockingQueuedConnection,当SOCKET有数据到达时就会发出readyRead()信号,
		此时可能之前receiveFile()还未执行完,用Qt::AutoConnection传输大文件时就会出错,
		原因在于只要有数据到达时就会连接信号但数据接收还没处理完毕,
		Qt::BlockingQueuedConnection会阻塞此连接,直到receiveFile()处理完毕并返回后才发送信号 
	
	qDebug()<<"run thread:"<<QThread::currentThreadId();  
	connect(tcpSocket,SIGNAL(readyRead()),this,SIGNAL(receiveSgl(tcpSocket))); 
	connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(receiveFile()),Qt::BlockingQueuedConnection); 
	exec();  
1.3.Qt线程间共享数据

说明:Qt本身类型直接传送。如自定义类型想用signal/slot不能直接使用
步骤:
1)定义数据类型:typedef unsigned short u16;//或类结构体
2)声明数据类型:Q_DECLARE_METATYPE(u16)    //在定义数据类型文件中声明

3)注册数据类型:构造函数(也可在mian.cpp中)
	qRegisterMetaType<u16>("u16")
	qRegisterMetaType(u16*)("u16*");     //指针
	qRegisterMetaType(u16*)("u16&");     //引用
4)信号槽关联:
	connect(...)                         //构造函数(也可在mian.cpp中)

 

2. 示例:
//U16.h
#pragma once
#include <QMetatype>

typedef unsigned short U16;
Q_DECLARE_METATYPE(U16); 
//MyThread.h
#pragma once
#include <QThread>

#include "U16.h"

class MyThread :public QThread{
	Q_OBJECT
public:
	MyThread(QObject *parent = Q_NULLPTR);
	~MyThread() { delete m_x3; }
	void set_data(U16 x1, U16 &x2,U16* x3);

public:
	void run();
signals:
	void thread_signal(U16 x1, U16 &x2, U16* x3);
public slots:
	void get_thread_signal(U16 x1, U16 &x2, U16* x3);

private:
	U16 m_x1=0,_m_x2=0;
	U16 &m_x2= _m_x2;
	U16 *m_x3=nullptr;
};
//MyThread.cpp
#include "MyThread.h"
#include <iostream>

MyThread::MyThread(QObject *parent) : QThread(parent) {
	if (m_x3 == nullptr) m_x3 = new U16(0);	
	connect(this, &MyThread::thread_signal, this, &MyThread::get_thread_signal, Qt::DirectConnection);
}

void MyThread::run() {
	set_data(m_x1, m_x2,m_x3);
	emit thread_signal(m_x1, m_x2,m_x3);
}

void MyThread::set_data(U16 x1, U16 &x2, U16* x3) { m_x1 = x1; m_x2 = x2;* m_x3 = *x3; }
void MyThread::get_thread_signal(U16 x1, U16 &x2, U16* x3) {
	std::cout << x1 <<";"<< x2 << ";" <<*x3<< std::endl;
}

 

//MyObject.h
#pragma once
#include <QObject>
#include "u16.h"
#include <iostream>
#include "MyThread.h"

class MyObject :public QObject{
	Q_OBJECT
public:
	explicit MyObject(MyThread *thread=nullptr,QObject *parent = Q_NULLPTR);
	~MyObject() { }

	void get_thread_signal(U16 x1, U16 &x2, U16* x3);

private:
	MyThread *mythread=nullptr;
};
//MyObject.cpp
#include "MyObject.h"
#include <QMetatype>

MyObject::MyObject(MyThread *thread,QObject *parent) :QObject(parent) {
	qRegisterMetaType<U16>("U16");
	qRegisterMetaType<U16*>("U16&");
	qRegisterMetaType<U16*>("U16*");

	mythread = thread;

	connect(mythread, &MyThread::thread_signal, this, &MyObject::get_thread_signal);
	//connect(mythread, &MyThread::finished, this, &QObject::deleteLater);
}

void MyObject::get_thread_signal(U16 x1, U16 &x2, U16* x3) {
	std::cout << "x1=" << x1 << "; &x2=" << x2 << "; *x3=" << *x3 << std::endl;
} 
//main.cpp
#include <QtCore/QCoreApplication>
#include <iostream>
#include "MyThread.h"
#include "MyObject.h"

int main(int argc, char *argv[]){
    QCoreApplication a(argc, argv);
	
	std::cout << "ready start thread..." << std::endl;
	MyThread t; MyObject obj(&t);
	U16 x1 = 1, x2 = 2,x3=3;
	t.set_data(x1, x2,&x3);
	t.start();

    return a.exec();
} 

 

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值