QEventLoop-qt阻塞异步操作

注意:前面都是基础讲解,如果有什么不懂的可以看看,但是如果只是追求实际运用场景,建议从问题时间开始看

这里是目录标题

原文

QEventLoop::QEventLoop(QObject *parent = nullptr)

Constructs an event loop object with the given parent.

它说,使用给定的父对象构造一个事件循环对象。

void QEventLoop::quit()

Tells the event loop to exit normally.

它说,告诉事件循环正常退出。

int QEventLoop::exec(QEventLoop::ProcessEventsFlags flags = AllEvents)
Enters the main event loop and waits until exit() is called. Returns the value that was passed to exit().
If flags are specified, only events of the types allowed by the flags will be processed.
It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets.
Generally speaking, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets use their own local event loop.
To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More sophisticated idle processing schemes can be achieved using processEvents().
See also QCoreApplication::quit(), exit(), and processEvents().
它说,进入主事件循环并等待直至调用exit()。返回传递给exit()的值。若指定了标志位,则仅处理标志位允许的事件类型。必须调用此函数以启动事件处理。主事件循环接收来自窗口系统的事件,并将其分发给应用程序控件。一般而言,在调用exec()之前无法进行用户交互。特殊情况是,诸如QMessageBox之类的模态控件可在调用exec()前使用,因为模态控件使用其自身的本地事件循环。若需实现应用程序空闲处理(即当无挂起事件时执行特定函数),可使用超时时间为0的QTimer。更复杂的空闲处理方案可通过processEvents()实现。另请参阅QCoreApplication::quit()、exit()和processEvents()。

辅助理解时间

你敢想象,它可以用在哪吗?好吧,摊牌吧:

对类似于能单独开辟"工作时间"的"单元",它具有独一无二的作用,就如标题描述一样,它能直接控住这些情况。

最简单的情况来说,你们知道QTimer吧!(假装知道吧)它是我们最好的帮手,能实现异步,当然它忠于我们,并不是不可控的,不过,偶尔皮一下,假装它不可控,这时候,合理利用上述三个函数,你会发现QTimer的执行开始有趣了!
此处非必要,不要看,就是偶尔有点思维发散,皮一下:就像你家熊孩子和你去游乐园,本来按计划,让你家熊孩子自己去逛多久,然后在某个地方汇合,但是来到游乐园,你突然来感觉了,说:快,你去上个厕所(QEventLoop loop),我等你拉完......。然后,你家熊孩子一脸便秘的去上厕所......,直到它假装拉完(loop.exec())......

问题时间

好了,好了,该上点强度了,以下是某一函数内的示例代码:

c 复制代码
QEventLoop loop;
int jobId = m_channel->downloadFile(remoteFilePath, localPath, QSsh::SftpOverwriteExisting);

connect(m_channel.data(), &QSsh::SftpChannel::finished, this, [&](QSsh::SftpJobId id, const QString &error) {
    writeLog("[fileInfoAvailable]:" + QString().number(__LINE__));
    writeLog("[fileInfoAvailable]:id " + QString().number(id) + " | jobId " + QString().number(jobId));
    if (id == jobId) {
        success = error.isEmpty();
        if (!success) {
            qDebug() << "Download failed:" << error;
        }
        else
        {
            writeLog("[fileInfoAvailable]:success");
            QString newProcess1 = fileInfo.name;
            newProcess = newProcess1.replace(".rar",".exe");
            decompression();
            progressTimer->stop();
        }
        loop.quit();
    }
});
loop.exec();

这里涉及了lambda槽函数,SFTP网络传输,有感兴趣的@作者,作者有时间会做一个案例指导,贯穿其它技术。

在这里,SFTP网络传输不可控,你不知道它会什么时候结束。因此强行让整个程序在这里等!

如果注释掉loop.exec();,你知道会发生什么吗?提示:看看局部变量吧。希望你看到后,能开心起来。

复制代码
     想必,你们早就看出来了,局部变量在这个过程中的体现在这里完美展示出来。哦,忘了告诉你们,按照正常逻辑,这里的局部变量只
可能是一个定值!
     案例中,局部变量jobId,在有无loop.exec()代码,会有两种结果,一种是3,一种是0。不知道你们有没有好奇过,在没有其它赋值的
情况下,它哪来的0.
     0的结果其实是因为,超出作用域后导致的!哎......当我想到这一层的时候,小脑都萎缩了一下,时间久了......真尬

同步举例时间

虽然上述案例,大部分人可能不会遇见,但如果想去试试的话,可以考虑你家乖孩子,QTimer去模拟上述的情况,lambda中的参数变量可以去掉。最后,为了更加深刻明显,你可以尝试在loop.exec();后面,加个打印,你会发现,你家乖孩子,在你的监督下,进了厕所,在不知多久后,它出了厕所,然后你就可以去打印门票了。

当然,作者没有用到自家乖孩子,纯属举一反三,如有问题,欢迎指正!

相关推荐
WWJA王文举5 小时前
I²C通信完整流程详解:START、地址、ACK、数据、Repeated START和STOP一次讲透
c语言·开发语言
zhanghaha13146 小时前
Python进阶教程:6_JSON 数据解析 —— 新手完全指南
开发语言·python·json
qq_448011167 小时前
C语言中的动态内存分配
c语言·开发语言·php
汉字萌萌哒8 小时前
2024CSP-J入门级C++真题详解
开发语言·c++
arbboter8 小时前
【网络工具】NetProxy网络代理用户手册
开发语言·网络·c#·网络代理·网络异常·代理工具
汉字萌萌哒9 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
叠层归一研究院9 小时前
AGI 系统(十一):二阶网络 — 二阶递归 × 多主体 (元符号网络)
开发语言·人工智能·算法·php·agi
小雨笙笙9 小时前
C语言:变量三属性——存储类型
c语言·开发语言
果果燕10 小时前
C++ 学习笔记(二):类与对象—— 构造函数与析构函数
开发语言·c++
江畔柳前堤10 小时前
Function Calling 与 Tool Calling:从认知到工程的全景深度解析
开发语言·网络·人工智能·深度学习·算法·机器学习·php