【问题标题】:How to temporarily switch to the GUI thread如何临时切换到 GUI 线程
【发布时间】:2021-05-16 23:03:55
【问题描述】:

我有一个需要长时间操作的程序,我在不同的线程上运行这个函数。我需要定期为用户更新信息,所以我向 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++ multithreading qt


【解决方案1】:

您需要在条件3之前调用BlockingQueuedConnection方法来检查用户选择了哪个选项。

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

【讨论】:

  • 当我们使用 BlockingQueuedConnection 调用线程时,我们将等待返回值。
  • 如果我在主循环 QMetaObject::invokeMethod(this, "test",Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, updateGui)); void Example::test() { cmd << "test \n"; } 中添加这行代码,那么什么也不会发生并且 updateGui 是错误的
  • updateGUI 变量是测试函数的返回值,如果要更改 updateGUI 变量,必须在测试函数中返回一个布尔值。请阅读官方文档------doc.qt.io/qt-5/qmetaobject.html#invokeMethod
  • 哦,谢谢,我还以为方法调用成功就写在这个变量里了,现在可以了
猜你喜欢
  • 2014-10-30
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多