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返回

 

解决办法:

创建两个对话框即可,不同对话框的事件循环不同,互不干扰

 

posted @ 2024-03-09 17:31  kelvin_yan  阅读(114)  评论(0编辑  收藏  举报