Why should nesting of QEventLoops be avoided?
在他的 Qt 事件循环、网络和 I/O API 演讲中,Thiago Macieira 提到应该避免嵌套
QEventLoop is for nesting event Loops... Avoid it if you can because it creates a number of problems: things might reenter, new activations of sockets or timers that you were not expecting.
任何人都可以扩展他所指的内容吗?我维护了很多使用模式对话框的代码,当调用
嵌套的事件循环会消耗 1-2kb 的堆栈。在典型的 32kb L1 高速缓存 CPU 上,它占用了 5% 的 L1 数据高速缓存。
它可以重新输入任何已经在调用堆栈上的代码。不能保证任何代码都设计为可重入的。我说的是你的代码,而不是 Qt 的代码。它可以重新输入已启动此事件循环的代码,除非您明确控制此递归,否则无法保证您最终不会耗尽堆栈空间。
在当前的 Qt 中,有两个地方由于长期存在的 API 错误或平台不足,您必须使用嵌套的
重新进入事件循环通常是由编写伪同步代码引起的,其中一个人感叹应该缺少
对于现代 C 来说,使用 C 20 协程是值得的;周围有一些基于 Qt 的实验,易于构建。
有堆栈协程的 Qt-native 实现:Skycoder42/QtCoroutings - 一个最近的项目,以及较旧的 ckamm/qt-coroutine。我不确定后一个代码有多新鲜。看起来这一切都在某个时候奏效了。
在没有协程的情况下干净地编写异步代码通常是通过状态机完成的,请参阅this answer以获取示例,以及与
个人轶事:我等不及 C 协程可以投入生产了,我现在用 golang 编写异步通信代码,并将其静态链接到 Qt 应用程序中。效果很好,垃圾收集器不引人注目,而且代码比带有协程的 C 更容易读写。我有很多使用 C 协程 TS 编写的代码,但将其全部移至 golang,我不后悔。
嵌套的事件循环会导致顺序倒置。 (至少在 qt4 上)
假设您发生了以下一系列事情
1 2 3 4 5 6 | enqueued in outer loop: 1,2,3 processing 1 => spawn inner loop enqueue 4 in inner loop processing 4 exit inner loop processing 2 |
所以你看到处理顺序是:1,4,2,3。
我根据经验说话,这通常会导致我的代码崩溃。