为什么我点击更多我的qt应用程序很慢?

时间:2017-04-25 10:02:32

标签: c++ qt network-programming qtnetwork

我有一个刷新按钮和一个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);
}

1 个答案:

答案 0 :(得分:3)

每次SessionManager :: downloadSessions()被称为AFAIS时,都会建立一个新的信号槽连接。因此,在15日“点击”,replyfinished()被调用15次。

所以要么只使用Qt :: UniqueConnection,要么只在构造函数上调用connect()一次。