信號槽與線程


很多情況下,不知道槽函數執行所處的線程而導致數據問題,程序崩潰

 

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()和信號發射所在的線程是否是同一個線程,是同一個就是直接,否則隊列


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM