信号槽与线程

很多情况下,不知道槽函数执行所处的线程而导致数据问题,程序崩溃

H文件

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_testQThread.h"
#include "QtGuiClass.h"
class QPushButton;
class testQThread : public QMainWindow
{
    Q_OBJECT

public:
    testQThread(QWidget *parent = Q_NULLPTR);
    QtGuiClass* testg;
    QThread* tmpthread;
    QPushButton* pButton;
private:
    Ui::testQThreadClass ui;
    //void on_pushButton_clicked();
public slots:
    void testD();
};
#pragma once

#include <QObject>

class QtClass : public QObject
{
	Q_OBJECT

public:
	QtClass(QObject *parent=nullptr);
	~QtClass();
	void testB();
signals:
	void testC();
};

S文件

#include "testQThread.h"
#include "QtGuiClass.h"
#include <QThread>
#include <QPushButton>
#include <QDebug>
#include <QTimer>
#include "QtClass.h"

// (Default)If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used.
// Otherwise, Qt::QueuedConnection is used.
// The connection type is determined when the signal is emitted.
testQThread::testQThread(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    tmpthread=new QThread;
    QWidget*pWidget = new QWidget(this);
    this->setCentralWidget(pWidget);
    pButton = new QPushButton("test",pWidget);
    QtClass* pClass=new QtClass;
    pClass->moveToThread(tmpthread);
    tmpthread->start();
    connect(pButton, &QPushButton::clicked, pClass,&QtClass::testB);//QueuedConnection
    pClass->testB();//主线程执行testB;
    connect(pClass, &QtClass::testC, this, &testQThread::testD);//QueuedConnection
    connect(pClass, &QtClass::testC, [=]() {
        qDebug() << "2  " << thread();
        qDebug() << "3  " << QThread::currentThread();
    }
    );//子线程执行 DirectConnection
    connect(pClass, &QtClass::testC, this, [=]() {
        qDebug() << "4  " << thread();
        qDebug() << "5  " << QThread::currentThread();
    }, Qt::QueuedConnection
    );//主线程执行
    connect(pClass, &QtClass::testC, this, [=]() {
        qDebug() << "6  " << thread();
        qDebug() << "7  " << QThread::currentThread();
    },Qt::DirectConnection
    );//子线程执行
    connect(pClass, &QtClass::testC, this, [=]() {
        qDebug() << "8  " << thread();
        qDebug() << "9  " << QThread::currentThread();
    }
    );//主线程执行 QueuedConnection
}

void testQThread::testD()
{
    qDebug() <<"10  " <<thread();
    qDebug() <<"11  " <<QThread::currentThread();
}
#include "QtClass.h"
#include <QDebug>
#include <QThread>
QtClass::QtClass(QObject *parent)
	: QObject(parent)
{
}

QtClass::~QtClass()
{
}

void QtClass::testB()
{
	qDebug() << thread();//Returns the thread in which the object lives.
	qDebug() << QThread::currentThread();
	emit testC();
}

总结:

当你明确知道你的槽函数要在哪个线程执行,请显示的使用连接方式,这样可以避免潜在的由于线程问题导致的崩溃

验证:(Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.

#include "testQThread.h"
#include "QtGuiClass.h"
#include <QThread>
#include <QPushButton>
#include <QDebug>
#include <QTimer>
#include "QtClass.h"

// (Default)If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used.
// Otherwise, Qt::QueuedConnection is used.
// The connection type is determined when the signal is emitted.
testQThread::testQThread(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    tmpthread=new QThread;
    QWidget*pWidget = new QWidget(this);
    this->setCentralWidget(pWidget);
    pButton = new QPushButton("test",pWidget);
    QtClass* pClass=new QtClass;
    pClass->moveToThread(tmpthread);
    tmpthread->start();
    connect(pClass, &QtClass::testC, this, &testQThread::testD);//QueuedConnection-》DirectConnection
    connect(pButton, &QPushButton::clicked, [=]() {
        emit pClass->testC();
    });//在主线程执行
}

void testQThread::testD()
{
    qDebug() <<"10  " <<thread();
    qDebug() <<"11  " <<QThread::currentThread();
}

这个时候connect(pClass, &QtClass::testC, this, &testQThread::testD);变成了直接连接了;因为信号发射时所在的线程是主线程,而接受者也在主线程所以是直接连接

判断直接连接和队列连接的方式是看 QThread::currentThread()和信号发射所在的线程是否是同一个线程,是同一个就是直接,否则队列

原文地址:https://www.cnblogs.com/likemao/p/8797569.html