首页 > 解决方案 > 如何临时切换到 GUI 线程

问题描述

我有一个需要长时间操作的程序,我在不同的线程上运行这个函数。我需要定期为用户更新信息,所以我向 GUI 线程发送一个信号。但有时我需要用户做出选择,我需要在GUI线程上显示QDialog并在用户选择一个选项时暂停慢线程,当用户完成选择后,将值返回给慢线程并继续它

它应该看起来像这样:

但我不知道如何停止和继续线程以及是否应该这样做。

标题:

class Example:public QObject
{
    //...
    Q_OBJECT
    void mainLoop();
    Example();
signals:
    void updateGUI(const QString &message);
    void sendQuestion(const QString &message);
    void continueMainLoop(const QString &answer);
private slots:
    void updatuGUIslot(const QString &message);
    void showQuestionDialog(const QString &message);
};

来源:

  Example::Example()
  {
    connect(this,&Example::updateGUI,this,&Example::updatuGUIslot);
    connect(this,&Example::sendQuestion,this,&Example::showQuestionDialog);
    
    std::thread t(&Example::mainLoop,this);
    t.detach(); 
    // in the project it is not in the constructor
  }

void Example::mainLoop() 
{
    while(some condition1)
    {
        // slow action
        if(some condition2)
            emit updateGUI("message");
        if(some condition3)
        {
            QString result;
            ThreadPtr th = this_thread(); // pseudocode
            connect(this,&Example::continueMainLoop,this,[&](const QString &answer) 
            {
                result = answer;
                th.continue(); // pseudocode
            });
            emit sendQuestion("question");
            th.wait(); // pseudocode
        }
        // slow action
    }
}
void Example::showQuestionDialog(const QString &message)
{
    // show dialog with question
    emit continueMainLoop("answer");
}
void Example::updatuGUIslot(const QString &message)
{        
    // update GUI
}

标签: c++multithreadingqt

解决方案


您需要在 condition3 之前使用 BlockingQueuedConnection 调用该方法,以检查用户选择了哪个选项。

bool updateGui ;
QMetaObject::invokeMethod(this, "showDialog",Qt::BlockingQueuedConnection,
                          Q_RETURN_ARG(bool, updateGui));
if(updateGui)
{
    //update GUI
}

推荐阅读