我有一个刷新按钮和一个SessionManager(一个会话只是一个开始日期和一个结束日期)。我希望当我点击刷新按钮时,会下载并显示会话。我没有问题。
但是当我点击很多次10次时,应用程序在10或15秒内没有回复。点击一次或两次我没有问题。
我读了调试输出,有很多下载相同的文件而不是一个下载。
这是我的SessionManager类;它下载了一个json文件
class SessionManager : public QObject
{
Q_OBJECT
bool m_has_reply_finished;
public:
explicit SessionManager();
void setAccessToken(const QString& accessToken);
void setTimeout(int timeoutMS = 3000);
const QString& getDownloadedSessions();
bool isDownloading();
bool isFinished();
signals:
void onSucceeded();
void onFailed();
void onTimeOut();
public slots:
void downloadSessions();
void replyfinished(QNetworkReply *reply);
void OnTimeOut();
private:
QString m_downloaded_sessions_string;
bool m_is_downloading;
QNetworkReply* m_last_network_reply;
QMutex m_mutex;
QNetworkAccessManager m_manager;
QString m_access_token;
int m_timeout_ms;
};
SessionManager::SessionManager(): m_has_reply_finished(false), m_is_downloading(false), m_last_network_reply(NULL), m_timeout_ms(3000)
{
}
void SessionManager::setAccessToken(const QString& accessToken)
{
m_access_token = accessToken;
}
void SessionManager::setTimeout(int timeoutMS)
{
m_timeout_ms = timeoutMS;
}
void SessionManager::downloadSessions()
{
if (m_is_downloading)
return;
m_has_reply_finished = false;
m_is_downloading = true;
QUrl url("http://website.com/api/seance");
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Accept", "application/json");
request.setRawHeader("Authorization", (QString("Bearer ") + m_access_token).toUtf8());
QTimer::singleShot(m_timeout_ms, this, SLOT(OnTimeOut())); // timeout => error
QObject::connect(&m_manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyfinished(QNetworkReply *)));
m_last_network_reply = m_manager.get(request);
}
const QString& SessionManager::getDownloadedSessions()
{
//QMutexLocker locker(&m_mutex);
return m_downloaded_sessions_string;
}
bool SessionManager::isDownloading()
{
//QMutexLocker locker(&m_mutex);
return m_is_downloading;
}
bool SessionManager::isFinished()
{
//QMutexLocker locker(&m_mutex);
return m_has_reply_finished;
}
void SessionManager::replyfinished(QNetworkReply *reply)
{
//QMutexLocker locker(&m_mutex);
if (reply == m_last_network_reply)
{
m_last_network_reply = NULL;
}
QString str = QObject::tr(reply->readAll());
if (!str.isEmpty())
m_downloaded_sessions_string = str.toUtf8();
m_has_reply_finished = true;
m_is_downloading = false;
// reply
if(reply->error() == QNetworkReply::NoError)
{
// JSON layer
//QJsonDocument d = QJsonDocument::fromJson(str.toUtf8());
//QJsonObject json = d.object();
//m_expires_in_seconds = (int64_t) json["expires_in"].toDouble();
//qDebug("SessionManager QNetworkReply::NoError");
emit onSucceeded();
}
else
{
//m_expires_in_seconds = 0;
//qDebug((QString("SessionManager QNetworkReply::Error (") + QString::number((int)reply->error()) + QString(")")).toUtf8());
emit onFailed();
}
//qDebug(str.toUtf8());
reply->deleteLater();
}
void SessionManager::OnTimeOut()
{
//QMutexLocker locker(&m_mutex);
if (m_last_network_reply)
{
m_last_network_reply->abort();
m_last_network_reply->deleteLater();
m_last_network_reply = NULL;
}
if(!m_has_reply_finished)
{
emit onTimeOut();
}
m_has_reply_finished = true;
m_is_downloading = false;
}
这是我的MainWindow。 MainWindow包含一个刷新按钮和插槽:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_sessionlist(NULL)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::Construct(AuthenticationManager * authentication_manager, SessionManager *session_manager)
{
m_authentication_manager = authentication_manager;
m_session_manager = session_manager;
connect(ui->sessionRefreshPushButton, SIGNAL (released()), this, SLOT(OnRefreshSessionsButtonClicked()));
QObject::connect(m_session_manager, SIGNAL(onSucceeded()), this, SLOT(OnDownloadSessionsSucceded()));
QObject::connect(m_session_manager, SIGNAL(onFailed()), this, SLOT(OnDownloadSessionsFailed()));
QObject::connect(m_session_manager, SIGNAL(onTimeOut()), this, SLOT(OnDownloadSessionsTimeOut()));
}
void MainWindow::OnRefreshSessionsButtonClicked()
{
qDebug("OnRefreshSessionsButtonClicked\n");
if (m_session_manager->isDownloading())
{
return;
}
ui->sessionRefreshPushButton->setEnabled(false);
ui->sessionRefreshPushButton->setVisible(false);
qDebug("m_session_manager->downloadSessions\n");
m_session_manager->setAccessToken(m_authentication_manager->accessToken());
m_session_manager->setTimeout(5000);
QTimer::singleShot(0, m_session_manager, SLOT(downloadSessions()));
}
void MainWindow::OnDownloadSessionsSucceded()
{
qDebug("OnDownloadSessionsSucceded\n");
LoadSessions();
ui->sessionRefreshPushButton->setEnabled(true);
ui->sessionRefreshPushButton->setVisible(true);
}
void MainWindow::OnDownloadSessionsFailed()
{
qDebug("OnDownloadSessionsFailed\n");
ui->sessionRefreshPushButton->setEnabled(true);
ui->sessionRefreshPushButton->setVisible(true);
}
void MainWindow::OnDownloadSessionsTimeOut()
{
qDebug("OnDownloadSessionsTimeOut\n");
ui->sessionRefreshPushButton->setEnabled(true);
ui->sessionRefreshPushButton->setVisible(true);
}
答案 0 :(得分:3)
每次SessionManager :: downloadSessions()被称为AFAIS时,都会建立一个新的信号槽连接。因此,在15日“点击”,replyfinished()被调用15次。
所以要么只使用Qt :: UniqueConnection,要么只在构造函数上调用connect()一次。