我在C++和Qt方面都是新手。这个类在我的项目中用于从web服务获取图像。
如果在前面的调用完成之前对StartDownload进行了新的调用,那么可以安全地丢弃旧的调用,因为不再需要它了。这是因为对每个调整大小事件提出了新的请求,因为服务的参数之一是图像大小(图像中的字体大小与图像大小相适应)。
因此,当请求被取消时,Qt会打印一个错误消息:QCoreApplication::postEvent: Unexpected null receiver。这不会干扰任何功能,但告诉我我没有正确地处理取消请求的问题。这些消息中有几条是在我调整窗口大小和调用CancelDownload时打印出来的。
除此之外,任何关于我的设计或C++成语的一般反馈都是受欢迎的!
注意:我使用的是C++11和QT5.6。
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QtNetwork/qnetworkaccessmanager.h>
#include <qbytearray.h>
#include <QObject>
class Downloader: public QObject
{
Q_OBJECT
public:
Downloader();
~Downloader();
void StartDownload(QUrl url);
private:
void CancelDownload();
QNetworkAccessManager mNetworkAccessManager;
QNetworkReply *mCurrentReply;
signals:
void DownloadFinished(QByteArray bytes);
private slots:
void HandleFinishedDownload();
};
#endif // DOWNLOADER_H#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
#include "Downloader.h"
Downloader::Downloader()
: mNetworkAccessManager(), mCurrentReply(Q_NULLPTR)
{
}
Downloader::~Downloader()
{
CancelDownload();
mNetworkAccessManager.deleteLater();
}
void Downloader::CancelDownload()
{
if (mCurrentReply != Q_NULLPTR) {
mCurrentReply->abort();
mCurrentReply->deleteLater();
mCurrentReply = Q_NULLPTR;
}
}
void Downloader::StartDownload(QUrl url)
{
CancelDownload();
QNetworkRequest request(url);
mCurrentReply = mNetworkAccessManager.get(request);
connect(mCurrentReply, &QNetworkReply::finished, this, &Downloader::HandleFinishedDownload);
}
void Downloader::HandleFinishedDownload()
{
if (!mCurrentReply) {
qCritical("Null reply in HandleFinishedDownload");
return;
}
if (mCurrentReply->error() == QNetworkReply::NoError) {
emit DownloadFinished(mCurrentReply->readAll());
}
else if (mCurrentReply->error() != QNetworkReply::OperationCanceledError) {
qWarning() << "Failed download:" << mCurrentReply->errorString();
}
mCurrentReply->deleteLater();
mCurrentReply = Q_NULLPTR;
}虽然我在一个自我回答中解决了上述问题,但我仍然在寻找一个全面的回顾!
发布于 2016-03-29 21:12:56
错误信息是由于我误解了deleteLater的目的而造成的。正如文献资料所暗示的,只有在删除槽内的对象(如HandleFinishedDownload )时,成员函数才是必需的。
注意:不要删除连接到error()或finished()信号的槽中的对象。使用deleteLater()。
在所有其他情况下,应该使用标准的delete关键字。因此,这里是CancelDownload的更新实现。
void Downloader::CancelDownload()
{
if (mCurrentReply != Q_NULLPTR) {
mCurrentReply->abort();
delete mCurrentReply; // this is the only altered line
mCurrentReply = Q_NULLPTR;
}
}https://codereview.stackexchange.com/questions/123709
复制相似问题