Warning: QDialog::exec: Recursive call detected
查看QDialog::exec的源码
int QDialog::exec() { Q_D(QDialog); if (d->eventLoop) { qWarning("QDialog::exec: Recursive call detected"); return -1; } bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose, false); d->resetModalitySetByOpen(); bool wasShowModal = testAttribute(Qt::WA_ShowModal); setAttribute(Qt::WA_ShowModal, true); setResult(0); ...
原因:QDialog的exec被递归调用,什么是递归调用?在上一次exec调用尚未返回又调用了一次exec
导致该错误的一种情况是多线程,UI线程exec对话框,某线程隐藏对话框,并在UI线程的exec返回之前又exec该对话框
另一种情况是UI线程的信号槽,在槽函数中结束对话框接着立马又exec一次对话框,因为同一线程的信号槽本身就是同步调用的(即信号发出的下一刻就会调用槽)。我的错误就是这个原因,实际场景如下:
1、主界面通过button启动了工作线程A,并弹出模态对话框阻塞用户操作;
2、等待线程A完成,主界面通过槽函数on_A接收线程A的完成信号
3、on_A内部,先关闭对话框,然后又启动了工作线程B,并exec同一个对话框阻塞用户操作;
4、等待线程B完成,主界面通过槽函数on_B接收线程B的完成信号
5、on_B内部,关闭对话框
在步骤3中,exec对话框没反应,对话框并没有弹出来,排除警告 QDialog::exec: Recursive call detected
上述过程的调用堆栈如下:
第一次exec调用
关闭第一次的对话框
第二次exec调用
Warning: QDialog::exec: Recursive call detected
第二次exec返回
关闭第二次的对话框
第一次exec返回
解决办法:
创建两个对话框即可,不同对话框的事件循环不同,互不干扰