百度了一会,发现没太有文字讲这件事情,因此整理成文字记录一下。


processEvents介绍

长时间运行的操作可以调用processEvents() 保持应用程序响应能力。

void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents)
根据指定的条件为调用线程处理一些待处理事件flags
void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
处理调用线程的待处理事件(Pending Events)达ms毫秒,或直到没有更多事件需要处理,以较短者为准。

关于ms参数的解释(来自GPT-3.5):

  • 如果正在处理事件的时间超过了指定的时间限制 ms,processEvents 函数仍然会等待事件处理完成,然后返回。
  • 如果事件处理完成前的时间限制 ms 达到了,那么 processEvents 函数将立即返回,即使事件队列中仍有待处理的事件。
  • 此处不太好验证,官方文档也没详写,经博主本人分析,gpt解释的合理

注意:
调用此函数时,线程切换去处理事件时,之前正在做的操作就被阻塞了,直到待处理事件完成。


问题代码及解决方法

问题代码:线程中有死循环,导致没有机会处理事件,执行槽函数。

解决方法:放开注释。使用QCoreApplication::processEvents();

// Work类的槽函数:

// 先触发这个槽函数,里面有while循环,会卡住线程
void Worker::doWork()
{
qDebug() << __FUNCTION__ << " Thread ID: " << QThread::currentThreadId() << "\n"; // 循环10次,每次1s
int i = 1;
while (i < 10)
{
i++;
Sleep(1000);
qDebug() << "second : " << i << " s\n"; //QCoreApplication::processEvents(); //
}
} // 再触发这个槽函数,会因为线程在做while循环,没有机会得到执行
void Worker::doWork2()
{
qDebug() << __FUNCTION__ << " Thread ID: " << QThread::currentThreadId();
} ---------------------------------------------------------------------------------------------------------- // Main函数中的代码
auto *worker = new Worker;
_workerThread = new QThread(this);
worker->moveToThread(_workerThread); // worker的槽函数都在_workerThread线程中执行 connect(this, SIGNAL(operate()), worker, SLOT(doWork(int)));
connect(this, SIGNAL(operate2()), worker, SLOT(doWork2(int))); // 启动线程
_workerThread->start(); emit operate(); // 先让线程中的while循环跑起来
emit operate2(); // 再触发doWork2槽函数,但是因为子线程中doWork在while循环,
// 此事件没有机会被处理,直至while循环结束才得到doWork2执行的机会。
结果1:
注掉QCoreApplication::processEvents(); 阻塞情况: Worker::doWork Thread ID: 0x4260 second : 2 s
second : 3 s
second : 4 s
second : 5 s
second : 6 s
second : 7 s
second : 8 s
second : 9 s Worker::doWork2 Thread ID: 0x4260
结果2:
放开注释 QCoreApplication::processEvents(); 解决阻塞问题后: Worker::doWork Thread ID: 0x4260 second : 2 s Worker::doWork2 Thread ID: 0x4260 // 执行processEvents时,如果有事件被阻塞了,立刻执行其槽函数 second : 3 s
second : 4 s
second : 5 s
second : 6 s
second : 7 s
second : 8 s
second : 9 s

Qt processEvents - 解决线程中事件阻塞(如槽函数被阻塞)的更多相关文章

  1. PyQt(Python+Qt)学习随笔:exit code 1073741845与槽函数所在对象不能定义同名实例方法问题

    最近做了几次测试,在PyQt中如果使用与槽函数同名的实例方法可能会导致不可控的错误. 案例1:如果两个信号映射到同名的槽函数,虽然参数不一样,但真正响应的槽函数是最后定义的槽函数,具体案例请见< ...

  2. 关于Qt在子线程中使用QMessageBox的折衷方法

    Qt将所有GUI相关的处理都限制在主线程中,这么做有助于防止意想不到的访问冲突产生,但也限制了线程中某些简单的UI交互的实现,比如QMessageBox. 因为QMessageBox必须在主线程中打开 ...

  3. PyQt(Python+Qt)学习随笔:Qt Designer中连接Action和槽函数

    在Designer中试了半天,终于找到了Action添加槽函数的方法,操作步骤: 在Designer右边界面中点击鼠标右键 确保信号/槽编辑被勾选,如图是未勾选的情况:. 勾选后会出现信号和槽的编辑界 ...

  4. 完美解决ListView中事件ItemCreated中使用ClientID导致插入数据失败

    于昨天晚上看到视频做到这个例子,但是发现始终有错误,在ListView的ItemCreated事件中使用了ClientID则会导致数据插入数据库失败.当点击插入按钮时,网页就像点击F5刷新一样,无任何 ...

  5. 使用Python+Qt时解决QTreeWidget中的内容超出边界后自动隐藏的问题

    问题: 默认情况下,内容超出边界后会自动省略,以...代替,而且无法出现水平滚动条 解决方法: 把VerticalScrollBar和HorizontalScrollBar的值都设为ScrollBar ...

  6. 解决iScroll中事件点击一次却触发两次的问题

    var t1=null;//全局 function myClick() { if (t1 == null){ t1 = new Date().getTime(); }else{ var t2 = ne ...

  7. QT paintevent 事件, update()槽函数

    一界面重载函数 使用方法: 1在头文件里定义函数 protected: void paintEvent(QPaintEvent *event); 2 在CPP内直接重载 void ---------- ...

  8. Qt发送一次信号触发两次槽函数的原因

    在手动为控件编写槽函数的时候,如果将槽函数名字按如下格式编辑,则不需要再次进行手动关联 void on_pushButton_1_clicked(); void on_radioButton_clic ...

  9. 重点:怎样正确的使用QThread类(很多详细例子的对比,注意:QThread 中所有实现的函数是被创建它的线程来调用的,不是在线程中)good

    背景描述: 以前,继承 QThread 重新实现 run() 函数是使用 QThread唯一推荐的使用方法.这是相当直观和易于使用的.但是在工作线程中使用槽机制和Qt事件循环时,一些用户使用错了.Qt ...

  10. promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

    * promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...

随机推荐

  1. S3C2440移植uboot之支持NAND启动

      上一节S3C2440移植uboot之新建单板_时钟_SDRAM_串口移植uboot初始化了时钟,配置了支持串口,这一节我们继续修改uboot支持NAND启动. 目录 1.去掉 "-pie ...

  2. freeswitch透传带SDP的180

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. freeswitch对于180/183的消息处理有默认的规则,但是在3GPP的标准中,消息流程会更加复杂,场景更多变. 这样就需要我 ...

  3. freeswitch的ACL规则

    概述 freeswitch是一款好用的VOIP开源软交换平台. VOIP公共网络中的安全问题是最重要的问题,我们必须对网络端口的访问权限做出限制. ACL全称Access Control List,意 ...

  4. liunx基础概述

    一.liunx起源 1.1991,芬兰研究生Liunus Torvalds编写了liunx的代码,并上传到互联网 2.Liunx基于UNIX,但是有别与UNIX 3.Liunx的软件产品使用了社区开发 ...

  5. maven开源仓库

    在公司开发一般都用公司内部的maven仓库,但回家之后,就访问不了公司的网络,使用不了公司的maven仓库,只能使用开源的maven仓库. 在网上搜索和整理了几个比较好用的maven开源镜像仓库,记录 ...

  6. spring启动流程 (2) Bean实例化流程

    本文通过阅读Spring源码,分析Bean实例化流程. Bean实例化入口 上一篇文章已经介绍,Bean实例化入口在AbstractApplicationContext类的finishBeanFact ...

  7. MyBatis04——使用注解开发

    使用注解开发 MyBatis3提供了新的基于注解的配置,但是MyBatis映射并不能用注解来构建. sql类型主要分成: @select @update @insert @delete 注意:利用注解 ...

  8. MySQL为什么不推荐使用in

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 当使用IN语句时,MySQL可能会遇到以下问题: ...

  9. 【转帖】nginx变量使用方法详解-4

    https://www.diewufeiyang.com/post/578.html 在设置了"取处理程序"的情况下,Nginx 变量也可以选择将其值容器用作缓存,这样在多次读取变 ...

  10. [转帖]OutOfMemory自动重启程序

    OutOfMemory以后程序已经假死,无法再提供服务,最好的做法是dump内存,发送警告,然后重启服务 我的方案:利用at命令延迟启动 但有一个问题,at最多支持分钟操作,也就是说要1分钟以后才能启 ...