Qt实现的生产者消费者模型解决UI刷新问题

Qt实现的⽣产者消费者模型解决UI刷新问题
实战场景
公司⼀个⽼项⽬, 客户反映程序有偶发性的界⾯错乱并卡死, 检查代码, 发现有两个⽹络线程同时在调⽤刷新界⾯的接⼝(且该UI接⼝是直接刷新, 没有缓冲机制). 这可是操作UI的⼤忌. ⽼项⽬的UI框架就不折腾了, 就把这⾥加个⽣产者消费者模型吧:
采⽤QWaitCondition和QMutex, 控制两个⽹络线程(NetThread1, NetThread2, 即两个⽣产者)将需要刷新的数据加⼊队列queue, 新增⼀个消费者线程(UpdateUiThread)以wait的⽅式监听这个queue, queue中有数据, 则取出数据去刷新UI.
模型
graph TD; NetThread1-->Queue; Queue-->UpdateUiThread; NetThread2-->Queue; linkStyle 0 stroke:#aaa,stroke-width:2px; linkStyle 1 stroke:#aaa,stroke-width:2px; linkStyle 2 stroke:#aaa,stroke-width:2px; style NetThread1 fill:#f9f,stroke:#000,stroke-width:1px style UpdateUiThread fill:#f9f,stroke:#000,stroke-width:1px style NetThread2 fill:#f9f,stroke:#000,stroke-width:1px style Queue
fill:#f9f,stroke:#000,stroke-width:1px王玉溪
钻井泥浆膨润土模型主要代码
netthread.cpp
#include "netthread.h"
cpld
#include <QDebug>解放军264医院
NetThread::NetThread(QWaitCondition *condition, QMutex *mutex, \
QQueue <QString>* queue, QObject *parent) : QObject(parent),
condition(condition),mutex(mutex), queue(queue)
{
//这⾥⽤⼀个定时器简单下模拟⽹络发送的数据
timer = new QTimer;
connect(timer, &QTimer::timeout, this , &NetThread::slotAddQueue);
timer->start(1000);
}
void NetThread::slotAddQueue()
{
mutex->lock();
queue->enqueue(threadId+"发来了数据!");
condition->wakeAll();
mutex->unlock();
}
updateuithread.cpp
#include "updateuithread.h"
#include <QDebug>
UpdateUiThread::UpdateUiThread(QWaitCondition *condition, QMutex *mutex, \
QQueue <QString>* queue, QObject *parent) : QObject(parent),
condition(condition), mutex(mutex), queue(queue)
{
}
void UpdateUiThread::slotUpdateUi()
{
while(1)
{
QString NetData;
if(queue->count() == 0)
编程语言实现模式{
mutex->lock();
4甲基吡啶
condition->wait(mutex);  /*⽣产者消费者模型, 主要是要理解wait的机制, wait时, 会阻塞在这⾥, 且同时也会把锁打开(让⽣产者(NetThread)可以向queue中插⼊数据).
⽣产者向queue中插⼊数据后, 需要调⽤condition.wakeall()或wakeone(), 当condition收到wake信号时, 会把锁重新锁上(暂时不让⽣产者向queue中插数据), 并开始执⾏此处后⾯的代码.*/
while(queue->count() > 0)
{//实际项⽬上是进⾏⼀系列⽐较耗时的UI更新操作, 这⾥⽤发送信号代替.
NetData = queue->dequeue();
emit signalUpdateUi(NetData);
}
mutex->unlock();
}
}
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QDebug>
#include "netthread.h"
#include "updateuithread.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
queue.clear();
this->netThread_1 = new QThread;
this->netThread_2 = new QThread;
this->updateUiThread = new QThread;
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
UpdateUiThread * updatethread = new UpdateUiThread(&condition, &mutex, &queue);    updatethread->moveToThread(updateUiThread);
connect(this, &Widget::startUpdateUi, updatethread, &UpdateUiThread::slotUpdateUi);    connect(updatethread, &UpdateUiThread::signalUpdateUi, this , [=](QString netData){        ui->plainTextEdit->appendPlainText(netData);
});
ui->plainTextEdit->appendPlainText("启动刷新UI线程");
updateUiThread->start();
emit startUpdateUi();
}
void Widget::on_pushButton_2_clicked()
{
NetThread *netthread1 = new NetThread(&condition, &mutex, &queue);
netthread1->setThreadId("⽹络线程1");
netthread1->moveToThread(netThread_1);
ui->plainTextEdit->appendPlainText("启动⽹络线程1");
netThread_1->start();
}
void Widget::on_pushButton_3_clicked()
{
NetThread *netthread2 = new NetThread(&condition, &mutex, &queue);
netthread2->setThreadId("⽹络线程2");
netthread2->moveToThread(netThread_2);
ui->plainTextEdit->appendPlainText("启动⽹络线程2");
netThread_2->start();
}
运⾏效果

本文发布于:2024-09-21 03:18:58,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/137389.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:刷新   模型   产者   数据   消费者
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议