QApplication :: exec()拒绝返回(在控制台程序中)

时间:2015-10-09 13:11:26

标签: c++ qt

我有一个Qt C ++程序,虽然它实际上并没有使用GUI(除了一些消息框弹出窗口),但使用了QApplication::exec() 方法(必要时运行事件循环并且可以服务整个信号/槽业务)。我还调用了QApplication::setQuitOnLastWindowClosed( false ),因为否则程序会在用户解除其中一个消息框弹出窗口时立即结束。我不认为这会对我观察到的行为产生任何影响,但我还是提到它,以防万一。

当然,在某些时候,程序应该结束,并且我已经添加了对QApplication::exit()的调用,导致Qt退出其事件循环,从而从QApplication::exec()调用返回。根据{{​​3}},这正是应该发生的事情。

  

int QApplication :: exec()

     

进入主事件循环并等待直到调用exit(),然后   返回设置为exit()的值(如果exit()为0则为0)   通过quit()调用。

然而,在我的计划中,它并没有发生。我已经在调试器中跟踪了程序流程,我确信已调用QApplication::exit(),但QApplication::exec()似乎还没有想要返回。 :(

我使用Qt 5.4.1和MinGW 3.11(GCC编译器将自己标识为版本4.9.1)。我的电脑运行的是Windows 7企业版(64位),Service Pack 1.有谁知道我可能做错了什么?

编辑:Kuba Ober在评论中提到QApplication::exec()可能没有返回,因为我的代码在某个地方阻塞了。我想发布主线程调用堆栈的屏幕截图,以证明主线程在此时深入到Qt的内部,并且我自己的代码实际上并不在控制之中。 / p>

Qt documention on the QApplication::exec() method

解决方案:好的,Rudolfs Bundulis'回答引导我解决问题的根源。我的程序中有一个小消息框弹出并要求用户执行某个操作(在这种情况下,打开一个与我的程序通信的外部设备)。为了使程序流程继续,没有必要忽略这个弹出窗口;只需打开外部设备就足够了,所以我忘了关闭消息框而不管它。后来,当QApplication::exit()被调用时,Qt似乎破坏了消息框(或至少使其不可见),因此它不能再被解雇,正如Rudolfs Bundulis指出的那样,一个开放的消息框足以保持QApplication::exec()返回。

1 个答案:

答案 0 :(得分:2)

您描述的机制应该有效。这是一个小代码段,有两种方式可以按照您的方式终止QApplication - 通过直接QApplication::quit()广告位或QApplication::exit()来电。两者似乎都有效。

QApplicationTerminator.h:

#pragma once

#include <QObject>
#include <QDebug>
#include <QApplication>

class QApplicationTerminator : public QObject
{
    Q_OBJECT

public slots:
    void quit()
    {
        qDebug() << "terminating QApplication\n";
        QApplication::exit(0);
    }
};

main.cpp中:

#include "qapplicationterminator.h"

#include <QApplication>
#include <QTimer>
#include <QDebug>
#include <QThread>

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    QApplicationTerminator terminator;
    QTimer::singleShot(3000, &application, SLOT(quit()));
    //QTimer::singleShot(3000, &terminator, SLOT(quit()));
    application.setQuitOnLastWindowClosed(false);
    auto result = application.exec();
    qDebug() << "event loop exited\n";
    return result;
}

我必须同意@KubaOber,你很可能要么在某个地方阻止。

由于您提到了对话框 - 对话框运行自己的事件循环,如果对话框的任何事件循环仍在运行(但是如果它们被正确使用则不会发生这种情况)主事件循环根本无法恢复控制并且无法退出。