您的位置:首页 > 房产 > 家装 > Qt|实现数据同步又不阻塞主界面

Qt|实现数据同步又不阻塞主界面

2024/12/21 19:54:21 来源:https://blog.csdn.net/weixin_42964413/article/details/140720148  浏览:    关键词:Qt|实现数据同步又不阻塞主界面

文章目录

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

需求

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

解决思路

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

子线程

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

// 子线程 防止阻塞主进程
#pragma once
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
class QThreadControl : public QThread
{Q_OBJECTpublic: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<Windows.h>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_;

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com