https://www.cnblogs.com/senior-engineer/p/5598133.html

https://www.cnblogs.com/findumars/p/5607683.html

api含义:QCoreApplication::processEvents() 将处理所有事件队列中的事件并返回给调用者。

问题描述:

当主线程在某个槽函数里正在执行processEvents时, 刚好有一个能响应此槽函数的信号发送过来了(肯定是其他线程发的信号),  这时就可能会发生可怕的递归,

导致栈溢出崩溃。 原因是processEvents,进入到无尽的递归中。

示例代码

bugThread.h

#include <QThread>
class BugThread : public QThread
{
Q_OBJECT
public:
BugThread(QObject* parent) : QThread(parent) {}
signals:
void sigBugsignal();
public:
void run()
{
while(true)
{
emit sigBugsignal();
}
}
};

bugs.h & bugs.cpp

class Bugs : public QMainWindow
{
Q_OBJECT public:
Bugs(QWidget *parent = 0, Qt::WFlags flags = 0);
~Bugs();
public slots:
void onBugSlot();
private:
Ui::BugsClass ui;
}; Bugs::Bugs(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
BugThread* bt = new BugThread(this);
connect(bt, SIGNAL(sigBugsignal()), this, SLOT(onBugSlot()));
bt->start();
} Bugs::~Bugs()
{ }
void Bugs::onBugSlot()
{
Sleep(1);
QApplication::processEvents();
}
===========================================================================================

有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态。例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响应用户的任何操作,窗口也不会重新绘制,从而处于“无法响应”状态,这是一个非常糟糕的体验 。

在这种情况下,有一种方法是使用多线程,即在子线程中处理文件保存,主线程负责界面相关。

而如果不想使用多线程,最简单的办法就是在文件保存过程中频繁调用QApplication::processEvents()。该函数的作用是让程序处理那些还没有处理的事件,然后再把使用权返回给调用者。

代码如下:

bool MyApp::writeFile(const QString &filename)
{
QFile file(filename);
...
QApplication::setOverrideCursor(Qt::WaitCursor);
for(int r = 0; r != rowCount; ++r)
{
for(int c = 0; c != colCount; ++c)
{
out << table(r,c);
qApp.processEvents();
}
}
QApplication::restoreOverrideCursor();
}

这样一来,程序就能响应了。

但是,该方法有一个问题:可能正在保存文件的过程中,用户不小心又单击了保存,或不小心关闭了程序主窗口,这样会产生意想不到的后果。

解决这个问题的最简单的办法是替换成:

qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件)。

进一步的,如果想显示一个带有进度条的对话框,随时显示当前的进度状态,可以使用QProgressDialog。

bool MyApp::writeFile(const QString &filename)
{
QFile file(filename);
...
QApplication::setOverrideCursor(Qt::WaitCursor);
QProgressDialog progress;
progress.setWindowTitle(tableData->sNameCH);
progress.setLabelText(QStringLiteral("数据保存中,请稍候..."));
//progress.setCancelButton(0);//不显示“取消”按钮
progress.setCancelButtonText("取消");
progress.setRange(0,rowCount );
progress.setModal(true);
//此处没有调用show()来显示,是因为QProgressDialog会自动决定是否显示
//如果时间过短,就不会显示。
for(int r = 0; r != rowCount; ++r)
{
progress.setValue(row);
//如果用户单击了“取消”,就取消保存文件,并删除该文件。
if(progress.wasCanceled)
{
file.remov();
return false;
}
for(int c = 0; c != colCount; ++c)
{
out << table(r,c);
qApp.processEvents();
}
}
QApplication::restoreOverrideCursor();
}

[C++]Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)的更多相关文章

  1. Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)

    有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...

  2. Qt 如何处理密集型耗时的事情

    有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...

  3. 使用ViewPager切换Fragment时,防止频繁调用OnCreatView

    使用ViewPager切换Fragment,我原先使用系统自带的适配器FragmentPagerAdapter. 切换fragment时,频繁调用oncreatview(). 查看FragmentPa ...

  4. mixare的measureText方法在频繁调用时抛出“referencetable overflow max 1024”的解决方式

    这几天在搞基于位置的AR应用,採用了github上两款开源项目: mixare android-argument-reality-framework 这两个项目实现机制大致同样.我选取的是androi ...

  5. javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题

    * 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...

  6. Qt 如何处理拖放应用程序参数时,中国

    你用 Qt 我们开发的应用程序.用户拖放文件到您的 exe 在.启动应用程序,在这个时候, main() 功能参数可以接收中国.如何正确处理它?非常easy,码如下面: QTextCodec *cod ...

  7. Qt事件分发机制源码分析之QApplication对象构建过程

    我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码: int main(int argc, char *argv[]) { QApplication application(argc ...

  8. Qt技巧:QProcess与外部程序的调用

    项目做到一定阶段,常常须要在原来的project上调用外部程序. Qt为此提供了QProcess类,QProcess可用于完毕启动外部程序,并与之交互通信. 一.启动外部程序的两种方式: (1)一体式 ...

  9. Qt一步一步实现插件调用(附源码)

    最近手里几个项目都采用插件的方式进行开发工作,这里记录一下实现方法,给需要的同学一个参考, 在linux系统和window系统都能成功编译通过,不废话直接步骤 第一步:建立插件原型 新建一个Qt项目, ...

随机推荐

  1. SourceTree 文件被锁异常

    公司用的代码管理工具是 Git 客户端用的是 SourceTree ,前些天 SourceTree 发生文件被锁异常,导致文件无法上传,下载,今天特意做个记录 异常: 解决方法:

  2. [转]REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR

    午睡一觉醒来,突然想伪造IP地址.搜了一下,Mark. 源地址:http://www.cnblogs.com/lmule/archive/2010/10/15/1852020.html ------- ...

  3. spy(主席树)

    题目链接 题目为某次雅礼集训... 对于\(\max\{a-A_i,\ A_i-a,\ b-B_i,\ B_i-b\}\),令\(x_1=\frac{a+b}{2},\ y_1=\frac{a-b}{ ...

  4. Hibernate的核心接口

    Hibernate5个核心接口 所有Hibernate应用中都会访问Hibernate的5个核心接口 Configuration接口:配置Hibernate,根启动Hibernate,创建Sessio ...

  5. 初窥Java--2(下载Eclipse,安装tomcat插件)

    一.软件下载 Eclipse3.6 IDE for Java EE Developers: 下载地址:http://eclipse.org/downloads/ Tomcat Eclipse Plug ...

  6. Mysql中大数据类型的存取

    标准SQL中提供了八种大数据类型 上面四种是针对字节数据(二进制字符串类型,主要存储图片.音频信息等),下面四种是针对字符数据(非二进制字符串类型,纯文本文件). MySql中不使用标准SQL中针对字 ...

  7. (转)为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调用

    我们常用wait(),notify()和notifyAll()方法来进行线程间通信.线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过 ...

  8. 函数的name属性

    匿名函数表达式的广泛使用加大了辨别函数的难度,所以ES6 中为所有函数新增了name属性 例如: name属性的特殊情况 (1) (2) 绑定函数的name属性总是由被绑定函数的name属性和字符串前 ...

  9. Eclipse Maven pom.xml 警告No grammar constraints (DTD or XML schema)

    消除警告方案: <?xml version="1.0" encoding="UTF-8" standalone="no"?> & ...

  10. 基于ELK5.1(ElasticSearch, Logstash, Kibana)的一次整合

    前言开源实时日志分析ELK平台(ElasticSearch, Logstash, Kibana组成),能很方便的帮我们收集日志,进行集中化的管理,并且能很方便的进行日志的统计和检索,下面基于ELK的最 ...