很多情況下,不知道槽函數執行所處的線程而導致數據問題,程序崩潰
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()和信號發射所在的線程是否是同一個線程,是同一個就是直接,否則隊列