Qt 多线程

Qt中实现多线程往往是构造一个数据处理类(继承Qobject),然后新建一个对象,将其依附于子线程(通过movetothread(QThread*)成员函数),通过signal-slot实现多线程。为何不是新建一个数据处理线程类来实现这个过称?
参考博文:https://blog.csdn.net/an505479313/article/details/50351745

connect函数第五个参数
要回答上面的问题,先简单介绍connect函数,官方文档

[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, 
const QObject *receiver, const char *method, 
Qt::ConnectionType type = Qt::AutoConnection)

第五个参数Qt::ConnectionType type = Qt::AutoConnection代表的是信号与槽的连接方式
在这里插入图片描述
AutoConnection
如果信号在接收者所依附的线程内发射,则等同于直接连接
如果发射信号的线程和接受者所依附的线程不同,则等同于队列连接
DirectConnection
当信号发射时,槽函数将直接被调用。
无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行。
QueuedConnection
当控制返回到接收方线程的事件循环时,将调用槽。插槽在接收方的线程中执行。
BlockQueuedConnection
与Qt::QueuedConnection相同,只是发出信号的线程会阻塞,直到槽返回。如果接收方处于发送信号的线程中,则不能使用此连接,否则应用程序将死锁。

QThread
QThread是管理线程的类,它所依附的线程和管理的线程不一样。比如
QThread 所依附的线程,就是执行 QThread t(0) 或 QThread * t=new QThread(0) 的线程。
QThread 管理的线程,就是 run 启动的线程。也就是次线程
见例子:https://blog.csdn.net/an505479313/article/details/50351745

定义一个 Dummy 类,用来发信号
定义一个 Thread 类,用来接收信号
重载 run 函数,目的是打印 threadid

/*!
* \file main.cpp
*
* Copyright (C) 2010, dbzhang800
* All rights reserved.
*
*/

#include <QtCore/QCoreApplication> 
#include <QtCore/QObject> 
#include <QtCore/QThread> 
#include <QtCore/QDebug>  
class Dummy:public QObject 
{ 
    Q_OBJECT 
public: 
    Dummy(){} 
public slots: 
    void emitsig() 
    { 
        emit sig(); 
    } 
signals: 
    void sig(); 
}; 
 
class Thread:public QThread 
{ 
    Q_OBJECT 
public: 
    Thread(QObject* parent=0):QThread(parent) 
    { 
        //moveToThread(this); 
    } 
public slots: 
    void slot_main() 
    { 
        qDebug()<<"from thread slot_main:" <<currentThreadId(); 
    } 
protected: 
    void run() 
    { 
        qDebug()<<"thread thread:"<<currentThreadId(); 
        exec(); 
    } 
}; 

#include "main.moc" 

int main(int argc, char *argv[]) 
{  
    QCoreApplication a(argc, argv); 
    qDebug()<<"main thread:"<<QThread::currentThreadId(); 
    Thread thread; 
    Dummy dummy; 
    QObject::connect(&dummy, SIGNAL(sig()), &thread, SLOT(slot_main())); 
    thread.start(); 
    dummy.emitsig(); 
    return a.exec(); 
}

结果

main thread: 0x1a40 from thread slot_main: 0x1a40 thread thread: 0x1a48

槽函数的线程和主线程是一样的!
如果想让槽函数slot在次线程运行(比如它执行耗时的操作,会让主线程死掉),怎么解决呢?
注意:dummy信号是在主线程发射的, 接收者 thread 也在主线程中。
参考我们前面的结论,很容易想到:
将 thread 依附的线程改为次线程不就行了?
这也是代码中注释掉的 moveToThread(this)所做的,去掉注释,你会发现slot在次线程中运行
结果

main thread: 0x13c0 
thread thread: 0x1de0 
from thread slot_main: 0x1de0

这可以工作,但这是 Bradley T. Hughes 强烈批判的用法。

推荐的方法
定义一个 Dummy 类,在run中发射它的信号
也可以在run中发射 Thread 类中的信号,而不是Dummy(效果完全一样)
QThread 定义槽函数,重载run函数

#include <QtCore/QCoreApplication> 
#include <QtCore/QObject> 
#include <QtCore/QThread> 
#include <QtCore/QDebug> 
 
class Dummy:public QObject 
{ 
    Q_OBJECT 
public: 
    Dummy(QObject* parent=0):QObject(parent)     {} 
public slots: 
    void emitsig() 
    { 
        emit sig(); 
    } 
signals: 
    void sig(); 
}; 
 
class Object:public QObject 
{ 
    Q_OBJECT 
public: 
    Object(){} 
public slots: 
    void slot() 
    { 
        qDebug()<<"from thread slot:" <<QThread::currentThreadId(); 
    } 
}; 
 
#include "main.moc" 
 
int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    qDebug()<<"main thread:"<<QThread::currentThreadId(); 
    QThread thread; 
    Object obj; 
    Dummy dummy; 
    obj.moveToThread(&thread); 
    QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot())); 
    thread.start(); 
    dummy.emitsig(); 
    return a.exec(); 
}

结果

main thread: 0x1a5c 
from thread slot: 0x186c

这样通过定义数据处理类(继承自QObject),通过movetothread依附于不同的线程,再通过connect函数可以灵活控制槽函数在哪个线程运行

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值