簡體   English   中英

避免GUI凍結多線程操作

[英]Avoiding GUI freezing on multithreaded operations

我有一個Qt GUI類preferencesWindow ,顯然,它負責處理用戶的首選項。 我有一些用於管理與數據庫服務器的連接的字段。 保留字段時,將dbsChanged()方法。 以下是我設法編寫的一些代碼:

void preferencesWindow::dbsChanged() {
    QFuture<QStringList> loader = run(this, &preferencesWindow::get_databases);
    QStringList databases = loader.result();

    if (databases.length()) {
        this->ui.database->show();
        this->ui.nodb_label->hide();
        this->ui.database->clear();
        this->ui.database->addItems(databases);
        this->ui.okButton->setDisabled(false);
        this->ui.validationStatus->setPixmap(QPixmap(":/icon/tick.png"));
    } else {
        this->ui.database->hide();
        this->ui.nodb_label->show();
        this->ui.okButton->setDisabled(true);
        this->ui.validationStatus->setPixmap(QPixmap(":/icon/error.png"));
    }
}
QStringList preferencesWindow::get_databases() {
    QSqlDatabase test_connection;
    if (QSqlDatabase::contains("PREFEREMCES_LIVE_TEST_CONNECTION"))
        test_connection = QSqlDatabase::database("PREFEREMCES_LIVE_TEST_CONNECTION");
    else test_connection = QSqlDatabase::addDatabase("QMYSQL", "PREFEREMCES_LIVE_TEST_CONNECTION");
    test_connection.setHostName(this->ui.serverAddress->text());
    test_connection.setUserName(this->ui.username->text());
    test_connection.setPassword(this->ui.password->text());
    test_connection.setDatabaseName(this->ui.database->currentText());
    test_connection.setPort(this->ui.serverPort->value());

    test_connection.open();
    qDebug() << "Error: " << test_connection.lastError();
    QSqlQuery show_databases = test_connection.exec("show databases");
    QStringList databases;
    while (show_databases.next()) {
        databases.append(show_databases.value(0).toString());
    }
    QSqlDatabase::removeDatabase("PREFERENCES_LIVE_TEST_CONNECTION");
    return databases;
}

由於get_databases可能要花費很長時間,因此我認為請放在這兩行中可以看到的單獨線程中:

QFuture<QStringList> loader = run(this, &preferencesWindow::get_databases);
QStringList databases = loader.result();

可以解決問題。 它在單獨的線程上運行,但是仍然凍結GUI(工作時)。

我應該如何重寫整個過程? 我雖然有一些解決方案,但我對它們的性能並不十分確定,也不想無用地工作...

它凍結了GUI,因為即使get_databases調用位於單獨的線程中,您仍然要等待導致凍結的結果。

我不知道如何在Qt中執行此操作,但是正常的情況是打開一個對話框,顯示“請稍候”或帶有取消按鈕的內容,並在以下情況下讓工作線程向父(GUI)線程發送信號:完成。

當您調用loader.result()時,QFuture將等待線程設置結果。 您必須稍后等待該值。

我想您可以在完成get_databases時將將來的對象存儲為preferencesWindow成員,並向自己發送signal 因此,您可以在這段等待時間內給應用程序時間來處理其他事件。

您可以使用QFutureWatcher來監視QFuture對象的狀態,如文檔中所述:

// Instantiate the objects and connect to the finished signal.
MyClass myObject;
QFutureWatcher<int> watcher;
connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished()));

// Start the computation.
QFuture<int> future = QtConcurrent::run(...);
watcher.setFuture(future);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM