[Qt学习笔记]Qt线程间数据通讯及数据共享

慈云数据 2024-04-01 技术支持 59 0

1、背景介绍

在使用QT做项目开发过程中,经常会用到多线程,比如图像采集一个线程,图像处理一个线程、数据通讯一个线程。这些不同的线程中会出现数据共享的需求,Qt线程间共享数据主要有三种方式:

1.使用共享内存;即两个线程都能够共享的变量(全局变量),这样两个线程都能够访问和修改变量,从而达到恭喜目的;

2.使用信号槽机制,将数据从一个线程传递到另外一个线程

3.共享类指针来进行访问不同类的变量和函数;

第三种是我自己常用的方法,在下面我总结记录一下。

2、 方法介绍

第一种方法,使用全局变量或全局函数,在其他类或线程中调用,这是各种编程语言中都通用的方法,但全局变量长时间占用内存,影响程序空间使用率,且全局变量修改影响整个程序,程序的安全性无法保证,一般尽量少用全局变量或函数,这种方法不展开介绍了。

2.1 信号槽进行数据通讯

信号槽功能是QT特有的功能,使用信号槽需要注意以下几个事项:

  1. 只有QObject类及其派生的类才能使用信号和槽的机制
  2. 在线程间使用信号槽进行通信时,槽参数必须使用元数据类型的参数;
  3. 如果使用自定义的数据类型,需要在connect之前将其注册(qRegisterMetaType)为元数据类型;
  4. 线程间用信号槽传递参数的话,要加const,因为const文字常量存在常量区中,生命周期和程序一样长。这样可以避免slot调用的时候参数的运行期已过造成引用无效;

这里我用一个balser相机线程采图使用信号槽发到UI线程显示的Demo来展示一下线程间通过信号槽的数据通讯。

/*图像采集线程头文件*/
/*GrabThread.h*/
#pragma execution_character_set("utf-8")
#ifndef _GRABTHREAD_H
#define _GRABTHREAD_H
#include 
#include 
#include 
#include 
#include 
#include "opencv2/opencv.hpp"
using namespace Pylon;
class GrabThread : public QThread
{
	Q_OBJECT
public:
	GrabThread();
	~GrabThread();
	void run();
    void init(CInstantCamera &m_camera);
	bool isInit();
	void stop();
	void save(bool);
	void grab(int g =1);
    cv::Mat Result2Mat(CGrabResultPtr &ptrGrabResult);
	CInstantCamera *m_camera;
	CGrabResultPtr ptrGrabResult; //Basler 获取结果指针
	CImageFormatConverter m_formatConverter;//Basler 图片格式转换类
	CPylonImage pylonImage; //Basler 图像格式
	QImage m_image; //Qt图片格式
	QPixmap m_pix;
	String_t m_prefix;
	bool m_stop;
	bool m_init;
	bool m_save;
	
	int m_grab; //获取图像策略 0表示连续获取,1表示获取单帧
	int m_num_one;
	int m_num_continue;
	
signals:
    //发给UI线程的信号
    void ThreadPic(cv::Mat outputPix);
};
#endif// GRABTHREAD_H

GrabThread.cpp

#include "GrabThread.h"
GrabThread::GrabThread()
{
	m_formatConverter.OutputPixelFormat = PixelType_Mono8;
	m_stop = false;
	m_init = false;
	m_save = false;
	m_grab = 0;
	m_num_continue = 0;
	m_num_one = 0;
}
GrabThread::~GrabThread()
{
}
void GrabThread::run()
{
	try
	{
		m_camera->StartGrabbing(GrabStrategy_LatestImageOnly);
		while (m_camera->IsGrabbing() && !m_stop)
		{
			m_camera->RetrieveResult(5000000, ptrGrabResult);
			if (ptrGrabResult->GrabSucceeded())
			{
				//格式转换
                cv::Mat MatImg = Result2Mat(ptrGrabResult);
                // qDebug() DetectProcess(img);
        qDebug()
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon