c++ - 如果从QRunnable或其他线程调用Qt信号和插槽,则它们不起作用

标签 c++ multithreading qt signals-slots qwidget

我正在尝试学习如何在Qt中使用多线程并将其在QtWidget应用程序中使用。因此,我已经设置了这个简单的测试用例。

主窗口
该表单有一些按钮,每个按钮将执行另一种表单(与此相关的对话框)。

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

    connect(ui->btnShowCalibrationDialog, &QPushButton::clicked,
            this, [&](){

        CalibrationDialog dlg;
        dlg.exec();
    });
}

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

CalibrationDialog 此对话框具有QPushButtonQTextEdit。单击该按钮后,我将运行QRunnable类(下一个!)

Calibrationdialog.h(我已为您省去了包含物和保护装置!)
    class CalibrationDialog : public QDialog
    {
        Q_OBJECT

    public:
        explicit CalibrationDialog(QWidget *parent = nullptr);
        ~CalibrationDialog();

    public slots:
        void onBeginWorkRequested();
        void onReceiveData(int data);

    private:
        Ui::CalibrationDialog *ui;
    };

标定对话框
#include "worker.h"

CalibrationDialog::CalibrationDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::CalibrationDialog)
{
    ui->setupUi(this);

    connect(ui->btnBegin, &QPushButton::clicked,
            this, &CalibrationDialog::onBeginWorkRequested);
}

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

void CalibrationDialog::onBeginWorkRequested()
{
    qDebug() << "CalibrationDialog::onBeginWorkRequested()" << "on" << QThread::currentThreadId();
    Worker* worker = new Worker();
    QThreadPool* pool = QThreadPool::globalInstance();
    connect(worker, &Worker::reportProgress,
            this, &CalibrationDialog::onReceiveData);
    pool->start(worker);
    pool->waitForDone();
}

void CalibrationDialog::onReceiveData(int data)
{
    ui->teResults->append(QString::number(data));
    ui->teResults->ensureCursorVisible();
}

Worker 这是一些可运行的...我想报告进度,以便以响应方式显示在对话框的textedit中!

worker
class Worker : public QObject, public QRunnable
{
    Q_OBJECT

public:
    explicit Worker(QObject *parent = nullptr);
    void run() override;

private:
    int mProgress = 0;

signals:
    void reportProgress(int progress);

};

worker.cpp
Worker::Worker(QObject *parent) : QObject(parent)
{

}

void Worker::run()
{
    qDebug() << "Worker is running #" << QThread::currentThreadId();
    while(true) {
        mProgress += 100;
        emit reportProgress(mProgress);
        QThread::msleep(500);
    }
}

我在调试器中看到控件进入了while循环...但是对话框未处理信号!我的意思是textedit保持为空!

我试图阅读文档并在线搜索...我得出的结论是,我的问题出在线程亲和力的荒原上....但我不知道是否是这种情况,以及如何解决。请协助!

最佳答案

删除pool->waitForDone();,切勿在GUI中使用waitForX方法,因为它们阻止了信号的执行。

关于c++ - 如果从QRunnable或其他线程调用Qt信号和插槽,则它们不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59571044/

相关文章:

c++ - 向 API 结构添加模板参数并保持与部分特化的向后兼容性

java - 为什么在线程调用启动时不调用定义的 run() 方法?

qt - 如何在键盘上仅显示带有 qt 的数字

c++ - Qt 中具有高度依赖函数的单元测试

c++ - '_mm_hadd_ps' 未在此范围内声明

c++ - 使用不相关的指针移动 shared_ptr

c++ - 处理异常时内存泄漏

java - concurrentLinkedQueue 提供/轮询阻塞

ios - 函数 'pthread_mutex_init' 的隐式声明在 C99 中无效

c++ - QT 运行但 QImages 不显示在发布版本中