QtConcurrent::run操作界面ui的注意事项(1)

本文介绍了在使用QtConcurrent::run进行耗时处理时,由于其运行在独立线程导致无法访问UI对象的问题,提出了两种解决方法:利用简单数据类型传递并更新UI,或在主线程循环中同步UI更新。同时指出,该方法在涉及网络IO操作时存在局限性。
摘要由CSDN通过智能技术生成

先说结论:QtConcurrent::run启动的耗时处理函数,不允许处理ui界面对象,如控件,如进度条等等!

QtConcurrent::run非常好用,胜过QThead的两种方式(run和moveToThread),例如下面是非常直观和简单的使用方式:

QT += concurrent

#include <QtConcurrent>
#include <QThread>


void MainWindow::doSomeWork()//死循环操作,代替原有代码的函数功能
{
   int i=0;
    while(myEnable)
    {
        i++;
        qDebug()<<i;
		QThread::msleep(10);
    }
}

void MainWindow::myStart()//启动函数是需要在原有代码基础上增加
{
	myEnable=1;
    QtConcurrent::run(this,&MainWindow::doSomeWork);//多线程执行死循环启动,可以带参数

void MainWindow::myExit()
{
    myEnable=0;//
}

但是,但是,上述的MainWindow::doSomeWork函数中不能访问ui对象,会引起程序崩溃!!原因后面解释。先说解决办法:

一种方法是,MainWindow::doSomeWork能读写简单类型的数值变量,int,float类型,则可以借助这些简单类型变量做个过渡中转一下。既然是ui界面对象,是给人看的,延时几十个ms,人的眼睛不会有感觉,因此,开一个定时器,轮询这些简单的数值int、float变量,在定时器里去更新ui界面对象,这是最简单的方法;

另一种方法是,在调用QtConcurrent::run(this,&MainWindow::doSomeWork)的地方,检查返回值,开一个循环等待完成。在循环里完成对界面ui的操作,如下面在按钮点击事件中:

void MainWindow::on_pushButton_clicked()
{
    ui->progressBar->setRange(0, 100); //使用进度条

    QFuture<void> future = QtConcurrent::run(this,&MainWindow::doSomeWork);//多线程执行死循环启动,可以带参数
	
    while(!future.isFinished())
    {
        ui->progressBar->setValue(m_curVal); //设置进度条当前值,m_curVal在doSomeWork中被更新
        QApplication::processEvents(QEventLoop::AllEvents, 100); //避免ui挂死
    }
}

上面依然是第一种方式的变种,只不过在循环里,借助了QApplication::processEvents(QEventLoop::AllEvents, 100),避免将ui挂死。

小结上述两种方法,第一种其实就是“共享全局变量”的变形;第二种是把循环直接写在ui的按钮事件里,让ui保持“灵活”;

再回到上述的:MainWindow::doSomeWork函数中不能访问ui对象,会引起程序崩溃!!

原因是,QtConcurrent::run本质是开启了另外一个子线程,该子线程和ui线程不相同,可以用:

qDebug()<<"当前线程 "<<QThread::currentThread();

分别加入到MainWindow的构造函数、on_pushButton_clicked()函数、doSomeWork()函数里验证,会发现,不在同一个线程里。这是qt的“跨线程”问题。

因为涉及到“跨线程”问题,总的来说,QtConcurrent::run并不好用,如果开启的线程里,要读写套接字tcp/udp、串口,是有问题的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值