关闭QCoreApplication的正确方式



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

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

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

我的代码如下:

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);
}

我得到以下输出:

下载完成!下载的文件大小。。。QWait状态:已毁坏而线程仍在等待。

据我所知,我想象中的一切都完成了。文件已下载,并显示其大小。但我想这个错误一定有意义。

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

您的代码有一些问题。您对待Qt就像它本质上是程序性的,而它实际上是通过主循环来事件驱动的。

首先,在QApplication循环开始之前调用qApp->exit(0)是错误的。根据Qt,"如果事件循环未运行,此函数将不执行任何操作。"您的事件循环尚未运行,因为您在调用exec 之前调用了doDownload

其次,在运行QApplication::exec时,您还没有创建任何要调度的顶级窗口或事件。我不确定当你在没有工作要做的情况下调用exec时会发生什么。当然,从语义上讲,对exec的调用没有任何作用。从技术上讲也许这会导致线程错误。同样,我不确定,但我知道您不应该以这种方式使用exec

运行您的主事件循环,然后完成所有您喜欢的Qt任务。这允许Qt调用您的代码。在Downloader中添加一个插槽doDownload和一个信号finished

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并启动主循环:,在建立控制反转后调用您的插槽

#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(),并且应该正确地清理所有内容。

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

相关内容

  • 没有找到相关文章

最新更新