我正在制作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);
}
我得到以下输出:
下载完成!下载文件大小... QWaitCondition:已销毁 线程仍在等待。
据我所知,我想象的一切都已完成。下载文件,并显示其大小。但我想这个错误必定意味着什么。
有人可以向我解释这个错误是什么,它为什么会发生以及如何修补它?
答案 0 :(得分:10)
您的代码存在一些问题。您正在将Qt视为本质上是程序性的,而它实际上是通过主循环事件驱动的。
首先,在qApp->exit(0)
循环开始之前调用QApplication
是错误的。根据Qt,“如果事件循环没有运行,则此函数不执行任何操作。”您的事件循环尚未运行,因为您在调用doDownload
<之前调用了exec
/ p>
其次,当您运行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();
}
然后通过调用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()
而不是明确退出应用程序,而且应该正确清理所有内容。
如果这可以解决您的问题,请告诉我。如果没有,可能还有其他鱼类可以炒。