gpt4 book ai didi

c++ - 线程和 GUI 处理

转载 作者:行者123 更新时间:2023-12-02 13:40:39 27 4
gpt4 key购买 nike

在我的应用程序中,我在线程和 GUI 消息(例如 QMessageBox 或新对话框)方面遇到一些问题。为了重现,我制作了一个小应用程序来显示问题:

主窗口.cpp

#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"

void ThreadAddTree::run() {

//mClass->addTreeEx();
bool b = false;
emit addTree(&b);
}


MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}


void MainWindow::on_pushButton_clicked()
{
QString path = "";
mThreadAddTree = new ThreadAddTree(this, path);
connect(mThreadAddTree, SIGNAL(addTree(bool*)), this, SLOT(on_add_tree(bool*)), Qt::BlockingQueuedConnection);
//,Qt::DirectConnection
mThreadAddTree->start();
}

void MainWindow::on_add_tree(bool* newData) {

QMessageBox::information(this, tr("Information"),
tr("Button click!"));

*newData = true;


}

void MainWindow::addTreeEx()
{
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtWidgets>
#include <QThread>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class ThreadAddTree : public QThread
{
Q_OBJECT
public:
ThreadAddTree(class MainWindow *nClass, const QString &path) {
mPath = path;
mClass = nClass;
}
signals:
void addTree(bool*);
protected:
void run();
QString mPath;
class MainWindow *mClass;
};

class MainWindow : public QMainWindow
{
Q_OBJECT
friend class ThreadAddTree;

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

void addTreeEx();

private slots:
void on_pushButton_clicked();

private:
Ui::MainWindow *ui;

protected:
ThreadAddTree *mThreadAddTree;


protected Q_SLOTS:
void on_add_tree(bool* newData);
};
#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

如果我在线程中使用调用:mClass->addTreeEx();,在非主 GUI 线程的情况下,应用程序将崩溃。明白了。

因此,我通过发出消息来解除调用 emit addTree(&b); 效果很好。显示消息框并且没有崩溃。

但现在对我来说变得复杂了。我需要在我的应用程序中调用 mClass->addTreeEx(); 因为它将执行一些操作。同样的函数也可以在附加线程之外使用。但在一种情况下,线程内运行的mClass->addTreeEx();需要调用Messagebox。

所以我的问题是,如何管理,我可以从函数 mClass->addTreeEx(); 发出 emit addTree(&b); 如果它从线程中调用,并且在没有 GUI 线程的情况下应用程序不会崩溃?

最佳答案

(在一定程度上)解释代码作者的意图并愿意纠正。

  • void addTree(bool*); 中的 bool* 类型的信号参数没有多大意义,特别是对于信号发送方具有 bool 变量的情况在堆栈上。要么使其void addTree(bool)并发送立即值,要么只是void addTree()并将槽侧的 bool 原子标志处理为std::atomic_bool thread_safe_flag; 因此,检查该标志将尽可能实际if (thread_safe_flag)。但这种处理需要更多的努力才能确保在正确的时间传递的信号与值同步。但这与 Qt 无关:Why do I need to acquire a lock to modify a shared "atomic" variable before notifying condition_variable可以使用或不使用 Qt 来完成。

  • UI 线程上的消息框阻止其他消息框出现的问题(这又是对作者代码问题的解释)。显然我们需要一个句柄来操作 message box ,比如说,关闭它,以防它已经打开:

    QMessageBox* m_msgBoxPtr{nullptr};
    std::atomic_bool m_threadSafeFlag;

    void UI_Class::mySlotToHandleMsgBox()
    {
    if (m_msgBoxPtr != nullptr) {
    m_msgBoxPtr->close();
    m_msgBoxPtr->deleteLater();
    m_msgBoxPtr = nullptr;
    mySlotToHandleMsgBox();
    }
    else {
    m_msgBoxPtr = new QMessageBox(QMessageBox::Information, title, message);
    m_msgBoxPtr->exec(); // assuming we want modal dialog as QMessageBox::information()
    // otherwise do m_msgBoxPtr->show()

    // if this is set on UI thread only then and no
    // "waits" for it on other threads then it being atomic is enough;
    // then don't bother with any sync "complications"
    m_threadSafeFlag = true;
    }
    }

关于c++ - 线程和 GUI 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59448565/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com