Qt|实现数据同步又不阻塞主界面
创始人
2024-11-15 04:33:32
0

文章目录

  • 需求
  • 解决思路
  • 子线程
  • 主线程

需求

调用第三方库的一个耗时函数,需要等待返回结果进行下一步,但是又不想阻塞Qt界面。

解决思路

创建子线程等待主线程调用,在主线程使用QEventLoop循环等待子线程返回执行结果,子线程内使用QWaitCondition,主要用于多线程编程,它提供了一种机制来同步线程间的操作,通过调用wakeOne()或wakeAll()方法唤醒等待的线程。

子线程

子线程继承QThread类,在run函数内执行任务,执行完后发送信号给主线程。
示例如下:
子线程头文件:

// 子线程 防止阻塞主进程 #pragma once #include  #include  #include  #include  class QThreadControl : public QThread { 	Q_OBJECT  public: 	QThreadControl(QObject* parent = nullptr); 	~QThreadControl();  	// 子线程执行函数 	void run() override; 	// 结束子线程 	void stop();  	// 等待返回数据 	QByteArray result();  signals: 	// 子线程执行完任务通知主线程 	void taskFinished(QByteArray);  public: 	// 发送数据并等待返回值的函数 	void sendSerialCommand(const QByteArray& command, CAMERA _current_camera);  	// 设置相关参数 	void setParameter(const QByteArray& command, CAMERA _current_camera);  	bool m_active;	// 保持线程活跃标志位 	自定义类对象 current_item_;	// 当前对象 	QByteArray command_;	// 控制指令 	QByteArray result_;		// 返回信息 	mutable QMutex m_mutex;	// 多线程加锁 	// 唤醒等待的线程 与互斥锁(QMutex)一起使用 以保护共享数据并同步线程 	QWaitCondition m_condition;  };  

子线程源文件:

#include "QThreadControl.h" #include  QThreadControl::QThreadControl(QObject* parent) { 	m_active = true; }  QThreadControl::~CameraCtrolLens() { 	stop(); 	wait(); }  void QThreadControl::run() { 	while (m_active) { 		QMutexLocker locker(&m_mutex); 		m_condition.wait(&m_mutex); 		if (!m_active) break;  		// 执行任务 		sendSerialCommand(command_, current_item_); 		// 任务完成后发送信号回主线程 		emit taskFinished(result_); 	} }  void QThreadControl::stop() { 	m_active = false; 	m_condition.wakeOne(); }  QByteArray QThreadControl::result() { 	QMutexLocker locker(&m_mutex); 	m_condition.wait(&m_mutex, 5000); // 等待最多5秒 	return result_; }  void QThreadControl::sendSerialCommand(const QByteArray& command,CAMERA _current_camera) { 	QByteArray revice_data(16, char(0)); 	if (_current_camera != nullptr) { 		int rev_num = 0; 		bool is_reviced = false; 		while (!is_reviced) 		{ 			if (revice_data.data() == QByteArray("waiting\r\n") || revice_data.data() == QByteArray("")) 			{ 				Sleep(100); 				//qDebug() << "send lens command waiting..."; 				++rev_num; 			} 			else 			{ 				is_reviced = true; 				break; 			} 			if (rev_num >= 80) 			{ 				revice_data.append("ERROR"); 				break; 			} 		} 	} 	else 	{ 		revice_data.append("ERROR"); 	} 	result_ = revice_data; }  void QThreadControl::setParameter(const QByteArray& command, 自定义类对象 _current_item) { 	QMutexLocker locker(&m_mutex); 	current_camera_ = _current_camera; 	command_ = command; 	m_condition.wakeOne(); }   

主线程

主线程调用如下所示,先设置参数,后创建loop循环,该循环会一直等待子线程任务结束退出,保证了返回值的数据同步,同时不会阻塞主界面操作。需要注意的是,主线程冲突按钮需要设置为不可用状态。

QByteArray test; test.append(_send_order); camera_ctrol_lens_->setParameter(test,current_camera_); // 创建事件循环对象 为了阻塞该函数等待结果返回 QEventLoop loop;  // 主循环,这里我们不需要循环,因为只需要执行一次任务 QObject::connect(camera_ctrol_lens_, &CameraCtrolLens::taskFinished, &loop, &QEventLoop::quit); // 进入事件循环,等待线程完成 loop.exec();  // 获取结果 return rev_value_; 

相关内容

热门资讯

绝活儿辅助!广西老友玩老是输怎... 绝活儿辅助!广西老友玩老是输怎么办(辅助挂)都是真的有辅助app(讲解有挂)在进入广西老友玩老是输怎...
法门辅助!福建13水插件(辅助... 法门辅助!福建13水插件(辅助挂)一贯是有辅助技巧(有挂技术)1、许多玩家不知道福建13水插件辅助怎...
办法辅助!潮友会app下载官方... 办法辅助!潮友会app下载官方辅助器(辅助挂)真是真的是有辅助app(有挂教程)该软件可以轻松地帮助...
妙招辅助!邯郸胡乐挂辅助(辅助... 妙招辅助!邯郸胡乐挂辅助(辅助挂)好像存在有辅助插件(有挂方略)1、上手简单,内置详细流程视频教学,...
教程书辅助!乐酷辅助(辅助挂)... 教程书辅助!乐酷辅助(辅助挂)其实存在有辅助脚本(有挂细节)乐酷辅助能透视中分为三种模型:乐酷辅助模...
学习辅助!决战卡五星辅助(辅助... 学习辅助!决战卡五星辅助(辅助挂)本来真的是有辅助软件(有人有挂)学习辅助!决战卡五星辅助(辅助挂)...
绝活辅助!边锋嘉兴麻将辅助器(... 绝活辅助!边锋嘉兴麻将辅助器(辅助挂)真是真的有辅助神器(新版有挂)1、边锋嘉兴麻将辅助器公共底牌简...
举措辅助!枫叶辅助器(辅助挂)... 举措辅助!枫叶辅助器(辅助挂)本来存在有辅助技巧(竟然有挂)1、下载好枫叶辅助器正确养号方法之后点击...
讲义辅助!点我达辅助(辅助挂)... 讲义辅助!点我达辅助(辅助挂)一直存在有辅助技巧(有人有挂)1、点我达辅助辅助器安装包、点我达辅助辅...
模块辅助!威信茶馆有挂的吗(辅... 模块辅助!威信茶馆有挂的吗(辅助挂)一直真的是有辅助脚本(揭秘有挂)1、玩家可以在威信茶馆有挂的吗线...