正确关闭QCoreApplication的方法

Ror*_*ach 2 ftp qt download qt5 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);

}
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

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

据我所知,我想象的一切都已完成.下载文件,并显示其大小.但我想这个错误必定意味着什么.

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

Ele*_*rks 10

您的代码存在一些问题.你正在对Qt进行处理,因为它本质上是程序性的,而它实际上是通过主循环事件驱动的.

首先,qApp->exit(0)QApplication循环开始之前调用是错误的.根据Qt," 如果事件循环没有运行,这个函数什么也不做." 您的事件循环尚未运行,因为您在调用doDownload之前已调用exec

其次,在您运行时QApplication::exec,您还没有创建任何顶级窗口或事件来分派.我不确定当你打电话exec没有工作时应该发生什么.当然,在语义上,呼吁exec什么都不做.技术上......也许它可能导致线程错误.同样,我不确定,但我知道你不应该以exec这种方式使用.

在完成所有花哨的Qt 之前运行主事件循环.这允许Qt调用您的代码.添加一个插槽doDownload和一个信号finished到您的Downloader.

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();
}
Run Code Online (Sandbox Code Playgroud)

然后通过调用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();
}
Run Code Online (Sandbox Code Playgroud)

现在Qt将调用您的代码.不是明确地退出应用程序,而是emit finished()应该正确地清理所有内容.

如果这解决了您的问题,请告诉我.如果没有,可能还有其他鱼类可以炒.