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


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. 5 Englishi 词根

    词根 1 ced/cess = go 行走 precede    pre=before   ced =go unprecedentedly  un   pre  ced +ed变成adj  +ly 变 ...

  2. echart自定义主题

    echart默认以canvas展示,放大会模糊,可以使用svg格式.

  3. 解决JedisNoReachableClusterNodeException,No reachable node in cluster报错

    通过jedis连接redis集群时报如下的错误:JedisNoReachableClusterNodeException,No reachable node in cluster 本机连接均正常:   ...

  4. Android Studio 的 Gradle 面板没有 Task

    问题描述:Android Studio Gradle 窗口没有显示 task 列表的问题,如下图所示: 网上找了好久都没有找到原因,最后自己摸索,找了解决方法. 解决方法:依次点击:File -> ...

  5. UofTCTF 2024 比赛记录

    这次的题目挺有意思,难度适中,*开头的代表未做出,简单记录一下解题笔记. Introduction General Information 题目 The flag format for all cha ...

  6. [转帖]Jmeter之JDBC Request使用方法(oracle)

    https://zhuanlan.zhihu.com/p/121747788 JDBC Request: 这个sampler可以向数据库发送一个jdbc请求(sql语句),它经常需要和JDBC Con ...

  7. [转帖]Day63_Kafka(一)

    第一讲 Kafka基础操作 课程大纲 课程内容 学习效果 掌握目标 Kafka简介 消息队列 掌握 Kafka简介 Kafka分布式环境 Kafka操作 Kafka shell 掌握 Kafka ap ...

  8. 神通奥斯卡数据库是否兼容Oracle, 以及参数修改的办法

    1. 最近公司要适配神通数据库, 但是因为一些功能异常.参数可能存在风险. 为了减少问题, 想着简单描述一下这些的处理. 开发和客户给的默认参数建议 1. 不选择 兼容oracle模式 2. 字符集选 ...

  9. 如何抓取http请求/拦截器用法

    我们都知道postman是模拟接口向服务端发送请求的,在编写请求数据的时候非常 麻烦,那么如果我们可以先抓取该接口后直接使用,就方便的很多 抓取http请求 1.我们打开postman时就会看见右上角 ...

  10. Element-UI中Drawer抽屉去除标题自带黑色边框

    当点击事件drawer==true时,抽匣回打开 这时抽匣的标题会出现一个难看的蓝色边框,一会就会消失,但是好丑,所以要去掉它 解决方法 /deep/ :focus { outline: 0; } v ...