In his ,Thiago Macieira 提到嵌套QEventLoop
应该避免:
QEventLoop 用于嵌套事件循环...如果可以的话请避免使用它,因为它会产生许多问题:事物可能会重新进入,套接字或计时器的新激活是您不期望的。
有人可以扩展他所指的内容吗?我维护了很多使用模态对话框的代码,这些对话框在以下情况下在内部嵌套一个新的事件循环:exec()
被称为所以我很想知道这可能会导致什么样的问题。
嵌套事件循环会占用 1-2kb 的堆栈。在典型的 32kb L1 缓存 CPU 上,它占用了 5% 的 L1 数据缓存。
它能够重新输入调用堆栈上已有的任何代码。无法保证任何代码都被设计为可重入的。我说的是你的代码,而不是Qt的代码。它可以重新输入已启动此事件循环的代码,除非您显式控制此递归,否则不能保证您最终不会耗尽堆栈空间。
在当前的 Qt 中,有两个地方由于长期存在的 API 错误或平台不足而必须使用嵌套exec
: QDrag
和平台文件对话框(在某些平台上)。您根本不需要在其他地方使用它。你不需要非平台模式对话框的嵌套事件循环。
-
重新进入事件循环通常是由编写伪同步代码引起的,其中人们感叹所谓的缺乏yield()
(co_yield
and co_await
现在已经登陆C++了!),把头埋在沙子里并使用exec()
反而。这样的代码通常最终会变成勉强可口的意大利面条,并且是不必要的。
对于现代 C++,使用 C++20 协程是值得的;有一些基于Qt的实验 https://github.com/jefftrull/coroutine_experiments周围,易于构建。
Stackful 协程有 Qt 原生实现:Skycoder42/QtCoroutings https://github.com/Skycoder42/QtCoroutines- 最近的项目和较旧的项目ckamm/qt 协程 https://github.com/ckamm/qt-coroutine。我不确定后面的代码有多新鲜。看起来这一切在某个时候都奏效了。
无需协程即可干净地编写异步代码通常是通过状态机完成的,请参阅这个答案 https://stackoverflow.com/a/32595398/1329652举个例子,和质量计划框架 http://www.state-machine.com对于与以下不同的实现QStateMachine
.
个人轶事:我迫不及待地想让 C++ 协程投入生产,现在我用 golang 编写异步通信代码,并将其静态链接到 Qt 应用程序中。效果很好,垃圾收集器不易察觉,而且代码比带有协程的 C++ 更容易读写。我有很多使用 C++ 协程 TS 编写的代码,但将其全部移至 golang,我并不后悔。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)