• QT多线程之:moveToThread


    不能在另外的线程直接delete一个QObject对象,相反,你需要调用QObject::deleteLater()函数,这个函数会给对象所在线程发送一个删除的事件。
    QObject的线程依附性是可以改变的,方法是调用QObject::moveToThread()函数。该函数会改变一个对象及其所有子对象的线程依附性。
    由于QObject不是线程安全的,所以我们只能在该对象所在线程上调用这个函数。也就是说,我们只能在对象所在线程将这个对象移动到另外的线程,不能在另外的线程改变对象的线程依附性。
    还有一点是,Qt 要求QObject的所有子对象都必须和其父对象在同一线程。这意味着:

    • 不能对有父对象(parent 属性)的对象使用QObject::moveToThread()函数
    • 不能在QThread中以这个QThread本身作为父对象创建对象,例如下面的代码片段:这是因为QThread对象所依附的线程是创建它的那个线程,而不是它所代表的线程。

    参考:QT 学习之路 2(74):线程和 QOBJECT


    class Test : public QObject
    {
        Q_OBJECT
    public:
        Q_INVOKABLE void show(int i) {
            qDebug()<<"show "<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    需要用Q_INVOKABLE声明,invokeMethod才能调用,否则会找不到show这个接口。

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        auto t = new Test;
        auto thread = new QThread;
        thread->start();
        int i = 0;
    
        qDebug()<<"main thread: "<show(i++);   // 0
        QMetaObject::invokeMethod(t, "show", Qt::DirectConnection, Q_ARG(int, i++));    // 1
        connect(this, &MainWindow::test, t, &Test::show);
        emit test(i++); // 2
        disconnect(this, &MainWindow::test, t, &Test::show);
    
        t->moveToThread(thread);
        qDebug()<<"after move to thread: "<show(i++);   // 3
        QMetaObject::invokeMethod(t, "show", Qt::DirectConnection, Q_ARG(int, i++)); // 4
        QMetaObject::invokeMethod(t, "show", Qt::QueuedConnection, Q_ARG(int, i++)); // 5
    
        connect(this, &MainWindow::test, t, &Test::show, Qt::DirectConnection);
        emit test(i++); // 6
        disconnect(this, &MainWindow::test, t, &Test::show);
        connect(this, &MainWindow::test, t, &Test::show);
        emit test(i++); // 7
        disconnect(this, &MainWindow::test, t, &Test::show);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述
    只有在线程启动后,并且通过信号槽和invokeMethod调用,且是队列的方式,才能让QOject子对象的show函数跑在子线程中。
    并非是将a实例相关的所有的工作“移动”到了m_thread线程,而是将所有a实例相关的事件托管到m_thread线程执行。换句话说,就是通过信号槽connect或者invokeMethod触发a实例中槽函数产生的事件,将会被放置到m_thread线程中执行。
    参考:[moveToThread实现多线程操作的理解(https://blog.csdn.net/yzt629/article/details/105429367)
    Q_INVOKABLE与invokeMethod用法全解

  • 相关阅读:
    827. 最大人工岛
    跨境电商建站:选择域名需要注意什么?
    redis 问题解决 1
    Python新特性
    使用trigger-forward跨流水线传递参数
    蓝桥杯 题库 简单 每日十题 day6
    408王道计算机组成原理强化——输入输出系统大题(I/O)
    Worthington蘑菇多酚氧化酶的特性及测定方案
    专业安卓实时投屏软件:极限投屏(QtScrcpy作者开发)使用说明
    QT环境下配置Assimp库(MinGW编译器)
  • 原文地址:https://blog.csdn.net/tanxuan231/article/details/127734351