我有一个派生自QObject的类'Downloader',它在一个工作线程中运行。线程启动时,下载程序在堆上创建一个QNetworkAccessManager对象,并开始请求文件。我会跟踪已请求和接收的文件数量。一旦我获得了所有文件,我就删除QNetworkAccessManager对象并退出该线程。我的问题是,无论何时何地,删除管理器对象都会导致崩溃。我甚至尝试过manager-> deleteLater()。如果我不删除它,我的代码运行良好,但我知道那里有内存泄漏。这是我的代码的精简版。
创建下载程序和线程,并设置信号以启动线程开始下载,下载完成后,线程停止:
QThread thread;
Downloader downloader;
downloader.setFiles(files);
downloader.moveToThread(&thread);
downloader.connect(&thread, SIGNAL(started()), SLOT(downloadFiles()));
thread.connect(&downloader, SIGNAL(downloadsFinished()), SLOT(quit()));
thread.start();
下载程序的实现:
void Downloader::downloadFiles()
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
receivedCount = 0;
requestCount = files.count();
for (QStringList::const_iterator pos = files.begin(); pos != files.end(); ++pos)
{
QUrl url(*pos);
manager->get(QNetworkRequest(url));
}
}
void Downloader::finished(QNetworkReply *reply)
{
// *** Get the file data and process it *** //
++receivedCount;
reply->deleteLater();
if (receivedCount == requestCount)
{
// manager->deleteLater();
emit downloadsFinished();
}
}
注释掉的行会使应用程序崩溃。即使在Downloader的析构函数中删除管理器,或将下载器设置为管理员的父级也会使应用程序崩溃。
我首先尝试将管理器创建为堆栈上的常规成员变量,但这样做会导致错误,因为管理器将在GUI线程中创建,然后尝试在不同的线程上创建子项。
之前任何人都说“QNetworkAccessManager是异步的。为什么在工作线程中使用它?”我有我的理由。做这样的事情不应该是闻所未闻。
答案 0 :(得分:4)
唯一明显的问题如下,但我不确定您是否已经发布了整个代码
void Downloader::downloadFiles()
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
您正在方法中创建本地 QNetworkAccessManager *manager
但不保留对它的引用,然后尝试在finished()方法中访问它。
您应该为new QNetworkAccessManager();
分配一个成员变量!