由于Qt仍然不支持在QNetworkRequest对象上设置超时,所以我编写了这个小包装类:
/**
Usage:
new QReplyTimeout(yourReply, msec);
When the timeout is reached the given reply is closed if still running
*/
class QReplyTimeout : public QObject {
Q_OBJECT
public:
QReplyTimeout(QNetworkReply* reply, const int timeout) : QObject(reply) {
Q_ASSERT(reply);
if (reply) {
QTimer::singleShot(timeout, this, SLOT(timeout()));
}
}
private slots:
void timeout() {
QNetworkReply* reply = static_cast<QNetworkReply*>(parent());
if (reply->isRunning()) {
reply->close();
}
}
};您可以以一种非常简单的火和遗忘的方式使用它:
QNetworkAccessManager networkAccessManger;
QNetworkReply* reply = networkAccessManger.get(QNetworkRequest(QUrl("https://www.google.com")));
new QReplyTimeout(r, 100);如果对Google的调用没有在100 is内完成,它将被中止。而且,由于QReplyTimeout类是QNetworkReply的父类,它将被自动销毁。
检查代码中是否存在任何缺陷、内存泄漏、无效的强制转换,以及它是否具有良好的风格。
发布于 2016-05-25 17:38:07
以下是我的想法:
QTimer::singleShot创建一个临时QObject实例,并在堆上分配一堆。您可以通过使用timerEvent显式地处理单次定时器来避免这种情况。您还避免了以这种方式设置任何连接的需要。当第一个连接被添加到QObject时,它会执行大约两次分配。ReplyTimeout这一事实是可以以这种方式抽象出来的各种实现细节。Q前缀命名类。这是为Qt预留的。下面的代码可以跨Qt 4和Qt 5移植:
class ReplyTimeout : public QObject {
Q_OBJECT
QBasicTimer m_timer;
public:
ReplyTimeout(QNetworkReply* reply, const int timeout) : QObject(reply) {
Q_ASSERT(reply);
if (reply && reply->isRunning())
m_timer.start(timeout, this);
}
static void set(QNetworkReply* reply, const int timeout) {
new ReplyTimeout(reply, timeout);
}
protected:
void timerEvent(QTimerEvent * ev) {
if (!m_timer.isActive() || ev->timerId() != m_timer.timerId())
return;
auto reply = static_cast<QNetworkReply*>(parent());
if (reply->isRunning())
reply->close();
m_timer.stop();
}
};使用:
QNetworkAccessManager networkAccessManger;
QNetworkReply* reply =
networkAccessManger.get(QNetworkRequest(QUrl("https://www.google.com")));
ReplyTimeout::set(reply, 100);https://codereview.stackexchange.com/questions/30031
复制相似问题