• 信号槽与线程


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

    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()和信号发射所在的线程是否是同一个线程,是同一个就是直接,否则队列

  • 相关阅读:
    ExternalInterface.addCallback()方法,as2 和 as3的区别
    关于table的display问题
    关于table的display问题
    js表单验证是否空值的简单处理办法
    《那些年啊,那些事——一个程序员的奋斗史》——112
    《那些年啊,那些事——一个程序员的奋斗史》——111
    《那些年啊,那些事——一个程序员的奋斗史》——113
    《那些年啊,那些事——一个程序员的奋斗史》——115
    《那些年啊,那些事——一个程序员的奋斗史》——112
    《那些年啊,那些事——一个程序员的奋斗史》——115
  • 原文地址:https://www.cnblogs.com/likemao/p/8797569.html
Copyright © 2020-2023  润新知