很多情况下,不知道槽函数执行所处的线程而导致数据问题,程序崩溃
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()和信号发射所在的线程是否是同一个线程,是同一个就是直接,否则队列