首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关闭QCoreApplication的正确方法

关闭QCoreApplication的正确方法
EN

Stack Overflow用户
提问于 2015-03-25 19:26:53
回答 1查看 11.5K关注 0票数 2

我正在制作一个Qt5 QCoreApplication,用于从FTP服务器下载文件(从HTTP开始,现在切换)。

当我的程序被关闭时,我遇到了一个问题。在我将exit(0)添加到downloader.cpp中之后,我的程序现在结束了,但是我得到了以下错误:

QWaitCondition:在线程仍在等待时销毁。

我的代码如下:

代码语言:javascript
复制
main.cpp

#include <QCoreApplication>
#include <downloader.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Downloader d;
    d.doDownload();

    a.exec();
}


**downloader.cpp**

#include "downloader.h"

Downloader::Downloader(QObject *parent) :
    QObject(parent)
{
}

void Downloader::doDownload() {

manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));

manager->get(QNetworkRequest(QUrl("ftp://ftp.fao.org/Public/GIEWS/windisp/40manual/wd4en.pdf")));
}


void Downloader::replyFinished (QNetworkReply *reply)
{

    if(reply->error()) {
        qDebug() << "ERROR!";
        qDebug() << reply->errorString();
    }
    else

    {
        qDebug() << "Download finished!";

        QFile *file = new QFile("C:/Users/jelicicm/Desktop/wd4en.pdf");

        if(file->open(QFile::Append))
        {
            file->write(reply->readAll());
            file->flush(); file->close();
            qDebug() <<"Downloaded file size:" <<(file->size())/1024<<"KB";
        }
        delete file;
    }

    reply->deleteLater();
    exit(0);

}

我得到以下输出:

下载完毕!下载的文件大小..。QWaitCondition:在线程仍在等待时销毁。

据我所知,我想象中的一切都已经实现了。文件被下载,并显示其大小。但我想这个错误一定意味着什么。

有人能向我解释一下这个错误是什么吗?为什么会发生这个错误,以及如何修补它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-25 22:47:10

您的代码有一些问题。您将Qt视为本质上的过程性处理,而实际上它是通过主循环由事件驱动的。

首先,在启动qApp->exit(0)循环之前调用QApplication是错误的。根据Qt,“如果事件循环没有运行,则此函数什么也不做。”您的事件循环尚未运行,因为在调用doDownload之前调用了exec

其次,在运行QApplication::exec时,您还没有创建任何顶级窗口或事件来进行调度。我不知道当你没有工作可做的时候打电话给exec会发生什么。当然,在语义上,对exec的调用什么也不做。严格来说..。也许它会导致线程错误。同样,我也不确定,但我知道您不应该以这种方式使用exec

做所有花哨的Qt操作之前,先运行主事件循环。这允许Qt调用您的代码。添加一个插槽,doDownload和信号,finished到您的Downloader

代码语言:javascript
复制
class Downloader : public QObject 
{
  Q_OBJECT

public:
  Downloader(QObject * parent = nullptr);

private slots:
  void doDownload();

signals:
  void finished();
}

...

void Downloader::doDownload() 
{
  // Same implementation as before
  // Emit signal when finished
  emit finished();
}

然后调用exec并启动主循环,在建立了控制反转后调用您的插槽:

代码语言:javascript
复制
#include <QCoreApplication>
#include "Downloader.h"

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);

  Downloader d;

  // Quit application when work is finished
  QObject::connect(&d, SIGNAL(finished()), &a, SLOT(quit())); // changed the 
  //variable name 'app' to 'a'

  // Run the user-hook (doDownload) from the application event loop.
  QTimer::singleShot(0, &d, SLOT(doDownload()));

  return a.exec();
}

现在Qt将调用您的代码。与其显式退出应用程序,不如简单地清除emit finished()和所有内容。

如果这能解决你的问题,请告诉我。如果没有,可能还有其他鱼要炸。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29264782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档