QThread线程学习笔记

1、QT版本

QT5.1

2、下面的测试程序在QtCreator的Qt Gui应用(QDialog)模板修改而成

3、下面是测试代码

头文件

#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
#include <QThread>
#include <QTimer>
class Object;
class Thread : public QThread
{
    Q_OBJECT
public:
    Thread(QObject *parent = 0);
Q_SIGNALS:
    void signalA();
private slots:
    void slotB();
    void slotT(); //响应定时器的槽
private:
    void run();
    //定义为类成员与在run()函数中定义该对象指针对线程执行没影响
    Object *object;
    QTimer *t;
};
 
 
class Object : public QObject
{
    Q_OBJECT
public:
    Object(QObject *parent =0);
public slots:
    void slotT();//响应定时器的槽
};
 
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
    
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    
Q_SIGNALS:
    void signalB();
 
private slots:
    void slotA();
    void slotBtnA();//响应按键ui->pushbutton
 
private:
    Ui::Dialog *ui;
    Thread *thread ;
};
 
#endif // DIALOG_H
 

源文件

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
 
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    thread = new Thread(this);
    connect(thread, SIGNAL(signalA()), this, SLOT(slotA()));
//    connect(this, SIGNAL(signalB()), thread, SLOT(slotB()));
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(slotBtnA()));
    qDebug()<<"Dialog Thread ID : "<<QThread::currentThreadId();
}
 
Dialog::~Dialog()
{
    delete ui;
}
 
void Dialog::slotA()
{
    qDebug()<<"Dialog::slotA Thread ID : "<<QThread::currentThreadId();
}
 
void Dialog::slotBtnA()
{
    Q_EMIT(signalB());
}
 
Thread::Thread(QObject *parent):
    QThread(parent)
{   //在构造函数定义(new)的对象都属于界面线程(主线程),下面测试的对象都在run()函数体里构建
    start();
}
 
void Thread::run()
{
    QTimer *t = new QTimer();
    object = new Object();
/*
 *object = new Object(this); 这样创建将会报警:
 *QObject: Cannot create children for a parent that is in a different thread.
 *(Parent is Thread(0x3dcea8), parent's thread is QThread(0x11fbe8d0), current thread is Thread(0x3dcea8)
 *但程序可以运行,且下面定时器响应槽slotT()是在子线程执行的
*/
    connect(t, SIGNAL(timeout()), this, SLOT(slotT()));//由于this这个对象属于主线程,故它的槽slotT是有主线程执行
    connect(t, SIGNAL(timeout()), object, SLOT(slotT())); //同理object在子线程创建,故它的槽slotT是由子线程执行
    t->start(3000);
    Dialog *parentDlg = qobject_cast<Dialog*>(parent());
    connect(parentDlg, SIGNAL(signalB()), this, SLOT(slotB()));//这个同上面一样,有主线程执行槽
    qDebug()<<"Sub Thread ID : "<<QThread::currentThreadId();
    Q_EMIT(signalA());
    exec();
}
 
 
void Thread::slotB()
{
    qDebug()<<"Thread::slotB Thread ID : "<<QThread::currentThreadId();
}
 
void Thread::slotT()
{
    qDebug()<<"Thread::slotT Thread ID : "<<QThread::currentThreadId();
}
 
 
void Object::slotT()
{
    qDebug()<<"Object::slotT Thread ID : "<<QThread::currentThreadId();
}
 
Object::Object(QObject *parent):
    QObject(parent)
{
}
 

 

由此可总结出:

1)、子类化QThread的类的构造函数,创建它的线程执行,创建出的对象(thread),属于创建它的那个线程;

2)、两线程通过信号与槽通信,槽函数由哪个线程执行,主要看其对象属于哪个线程(即创建它的那个线程),和connect的调用位置无关

3)、在子线程中创建对象时,主要避免使用父线程创建的对象作为父对象

 

 为了在子线程中处理耗时逻辑,使用上面这种信号和槽的连接方法,虽然可用,但连接的信号和槽太多,太乱,特别是子线程还要返回执行结果的情况下,又要定义一组信号和槽。所以可以使用

QMetaObject::invokeMethod
 

void MainWindow::slotBtnClick()
{
    int retVal = 0;
    int a = 1;
    int b = 1;
    //QMetaMethod::invoke: Unable to invoke methods with return values in queued connections
    //bool bInvoke = QMetaObject::invokeMethod(&m_thread, "slotAdd", Qt::AutoConnection, Q_RETURN_ARG(int, retVal), Q_ARG(int, a), Q_ARG(int, b));
    //bool bInvoke = QMetaObject::invokeMethod(&m_thread, "slotAdd", Qt::QueuedConnection, Q_RETURN_ARG(int, retVal), Q_ARG(int, a), Q_ARG(int, b));
    bool bInvoke = QMetaObject::invokeMethod(&m_thread, "slotAdd", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, retVal), Q_ARG(int, a), Q_ARG(int, b));
    
    qDebug()<<"QMetaObject::invokeMethod "<<bInvoke<<" a+b= "<<retVal;
    qDebug()<<"MainWindow::slotBtnClick() Thread ID : "<<QThread::currentThreadId();
}
注意:线程间调用只有BlockingQueuedConnection才可以使用返回值

int Thread::slotAdd(int a, int b)
{
    int c = a + b;
    qDebug()<<"Thread::slotAdd Thread ID : "<<QThread::currentThreadId();
    return c;
}
 

 结果

Thread::run() Thread ID : 0x1e08

Thread::slotAdd Thread ID : 0x1e08

QMetaObject::invokeMethod true a+b= 2

MainWindow::slotBtnClick() Thread ID : 0x3310 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值