首页 > 解决方案 > QT 多线程中 UI 显示的延迟

问题描述

我有一个多线程应用程序。我的应用程序有 2 个对话框:主对话框 ( Dialog1) 和事务对话框 ( Dialog2)。当应用程序运行时,Dialog1会开始QThread下载一个大文件。下载时Dialog2会显示。Dialog2将显示下载状态。请注意,即使Dialog2显示 ,下载仍将继续。显示时Dialog2,将启动轮询线程。当检测到卡时,该线程将处理交易。

问题:当检测到卡时,Dialog2应该更新 UI(我为此使用了信号和插槽)。但是,更新 UI 会延迟。或者需要几秒钟才能向 UI 显示正确的消息。这只发生在下载正在进行时。

下面是我的代码:

对话1:

void Dialog1::startDownlaod()
{
    DownloadClass *downloadClass ;

    Dialog2 *dialog2 = new Dialog2 (this);

    cout << "[Dialog2] from main thread: " << QThread::currentThreadId() << endl;

    downloadClass = new DownloadClass ();

    pAppDownloadThread_ = nullptr;
    pAppDownloadThread_ = new QThread();
    downloadClass->moveToThread(pAppDownloadThread_);
    connect(pAppDownloadThread_, SIGNAL(started()), downloadClass , SLOT(processDownloadRequest()));
    connect(downloadClass , SIGNAL(finished()), pAppDownloadThread_, SLOT(quit()));
    connect(downloadClass , SIGNAL(finished()), downloadClass , SLOT(deleteLater()));
    connect(pAppDownloadThread_, SIGNAL(finished()), pAppDownloadThread_, SLOT(deleteLater()));
    connect(downloadClass , SIGNAL(updateDownloadStatus()), dialog2, SLOT(updateDownloadStatus()));

    pAppDownloadThread_->start();

    dialog2->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    dialog2->exec();
}

下载器类:

class DownloadClass : public QObject
{
    Q_OBJECT

public slots:
    void processDownloadRequest();

signals:
    void finished();
    void onUpdateDownloadStatus();
}

对话2:

// this is the slot that will update downlaod status
void Dialog2::updateDownloadStatus()
{
    ui->labelStatus.setText("some text here");
}

// this is method to start the poller thread
void Dialog2::startPollingThread()
{   
    pollingThread_ = new QThread;

    Poller::instance()->moveToThread(pollingThread_); // singleton

    connect(pollingThread_, SIGNAL(started()), Poller::instance(), SLOT(poll()));
connect(Notifier::getInstance(), SIGNAL(displayMessage(QString)), this, SLOT(displayMessage(QString)));
    connect(Poller::instance(), SIGNAL(finished()), pPollingThread_, SLOT(quit()));
    connect(pPollingThread_, SIGNAL(finished()), Poller::instance(), SLOT(deleteLater()));
    connect(pPollingThread_, SIGNAL(finished()), pPollingThread_, SLOT(deleteLater()));

    cout << "[Dialog2] from main thread: " << QThread::currentThreadId() << endl;
    pollingThread_->start();
}

轮询器类:

class Poller : public QObject
{
    Q_OBJECT

public slots:
    void poll();

signals:
    void finished();
    void displayMessage(QString message);
}

// poll() method
void Poller::poll()
{
    if(isCardDetected)
        emit displayMessage("Detected"); // this will be sent to Dialog2 to display the message in the label
    else
        emit displayMessage("No card detected");
}

这是我打印 threadID 时的输出:

[Dialog2] from main thread: 0xb6fed000
[Dialog1] from main thread: 0xb6fed000
[Poller] from poller thread: 0xb0aff400
[DownloadClass] from downloader class: 0xb02ff400

请注意threadID和是相同的Dialog1Dialog2

标签: qtqthread

解决方案


推荐阅读