【Qt】多线程QThread::run()与QObject::moveToThread()

这篇具有很好参考价值的文章主要介绍了【Qt】多线程QThread::run()与QObject::moveToThread()。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

官方链接QThread Class | Qt Core 5.15.14

使用QThread::run()

简单来说就是继承QThread类,并重写run()函数,这样run()函数中的代码就会运行在子线程中。

QThread对象管理着一个线程,并通过start函数启动这个线程,线程要执行的代码都在run()里面,run()函数的进入和返回,就相当于子线程的启动和结束。

但是run()函数何时返回呢?一般有三种情况:

  1. run中代码走一遍就返回了。
  2. run中有while循环,在循环中有退出循环的flag变量,由外部程序置位这个flag,使循环退出,从而返回。
  3. run中最后一行是事件循环exec(),即程序会卡在这一行:this->exec();这种情况需要调用exit()或者terminate()才能让事件循环停下,从而让run返回。

当run函数执行完毕的时候,新线程也就结束了,并且发出finished()信号。

#ifndef SOMETHINGTHREAD_H
#define SOMETHINGTHREAD_H

#include <QThread>
#include <QObject>

class SomethingThread : public QThread
{
    Q_OBJECT
public:
    explicit SomethingThread(QObject *parent = nullptr);

    void run() override;//线程函数

private: signals:
    void resultReady(const QString result);//如果有线程计算结果返回,可以通过这种方式

};

#endif // SOMETHINGTHREAD_H
#include "somethingthread.h"
#include "qdebug.h"

SomethingThread::SomethingThread(QObject *parent)
    : QThread{parent}
{

}

void SomethingThread::run()
{
     for(int i=0;i<10;i++)
     {
         qDebug()<<"doing something %d"<<i<<" thread_id"<<QThread::currentThreadId();
         QThread::sleep(1);
     }
     emit this->resultReady("finish");//触发信号,传递结果参数
}
    SomethingThread* sth=new SomethingThread(this);
    connect(sth,&SomethingThread::resultReady,this,&SIHToolBar::onResultReady);//使用接收结果
    connect(sth,&SomethingThread::finished,sth,&QObject::deleteLater);
    sth->start();


void SIHToolBar::onResultReady(const QString result)
{
    qDebug()<<"onResultReady result="<<result<<" thread_id="<<QThread::currentThreadId();
}
doing something %d 0  thread_id 0x6188
doing something %d 1  thread_id 0x6188
doing something %d 2  thread_id 0x6188
doing something %d 3  thread_id 0x6188
doing something %d 4  thread_id 0x6188
doing something %d 5  thread_id 0x6188
doing something %d 6  thread_id 0x6188
doing something %d 7  thread_id 0x6188
doing something %d 8  thread_id 0x6188
doing something %d 9  thread_id 0x6188
onResultReady result= "finish"  thread_id= 0x2f0

有几点需要注意:

  • QThread类中的run()函数默认实现是这样的QThread::run() { this->exec(); },也就是默认开启了事件循环。
  • 只有run函数中的代码段是在子线程中执行的。如果run中使用了成员变量,而且其他地方也使用到了它,这时需要自行检查是否线程安全。
  • run函数中发射的信号,连接了使用它的对象的槽函数,实际上是跨线程了的。
  • 官方不推荐使用这种方式

使用QObject::moveToThread()

moveToThread 方法,是把我们需要的工作全部封装在一个类中,将每个任务定义为一个槽函数,再建立触发这些槽函数的信号,然后连接信号和槽,最后调用 moveToThread 方法将这个类交给一个 QThread 对象,再调用 QThread 的 start() 函数使其全权处理事件循环。于是,任何时候我们需要让子线程执行某个任务,只需要发出对应的信号就可以。

#ifndef WORKER_H
#define WORKER_H

#include <QObject>

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);

signals:
    void resultReady(const QString& result);//线程完成工作时发送的信号

public slots:
    void doWork(const QString& param);//定义了线程要执行的操作

};

#endif // WORKER_H
#include "worker.h"
#include <QDebug>
#include <QThread>

Worker::Worker(QObject *parent)
    : QObject{parent}
{

}


void Worker::doWork(const QString &param)
{
    for(int i=0;i<10;i++)
    {
        qDebug()<<"doWork %d"<<i<<" thread_id"<<QThread::currentThreadId();
        QThread::sleep(1);
    }
    emit this->resultReady("finish");//触发信号,传递结果参数
}
#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <QObject>
#include <QThread>
class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    explicit Controller(QObject *parent = nullptr);
    ~Controller();

signals:
    void doWork(const QString& param);//发送信号 触发线程

public slots:
    void onResultReady(const QString& result);//处理子线程执行的结果

};

#endif // CONTROLLER_H

#include "controller.h"
#include "worker.h"
#include <QDebug>
Controller::Controller(QObject *parent)
    : QObject{parent}
{
    Worker* work=new Worker();
    work->moveToThread(&this->workerThread);//调用moveToThread将该任务交给

    connect(&this->workerThread,&QThread::finished,work,&QObject::deleteLater);//当线程结束的时候,销毁worker对象
    connect(this,&Controller::doWork,work,&Worker::doWork);//通过controller的dowork信号 连接 worker对象的doworker槽函数
    connect(work,&Worker::resultReady,this,&Controller::onResultReady);
    workerThread.start();

    qDebug()<<"main thread_id="<<QThread::currentThreadId();
    emit this->doWork("start");
    //work->doWork("start");//这种直接调用的方式没有在子线程中执行
}

Controller::~Controller()
{
    workerThread.quit();
    workerThread.wait();
}

void Controller::onResultReady(const QString &result)
{
    qDebug()<<"onResultReady result="<<result<<" thread_id="<<QThread::currentThreadId();
}
main thread_id= 0x7254
doWork %d 0  thread_id 0x5970
doWork %d 1  thread_id 0x5970
doWork %d 2  thread_id 0x5970
doWork %d 3  thread_id 0x5970
doWork %d 4  thread_id 0x5970
doWork %d 5  thread_id 0x5970
doWork %d 6  thread_id 0x5970
doWork %d 7  thread_id 0x5970
doWork %d 8  thread_id 0x5970
doWork %d 9  thread_id 0x5970
onResultReady result= "finish"  thread_id= 0x7254

有几点需要注意:文章来源地址https://www.toymoban.com/news/detail-475313.html

  • 任何对象只要执行了moveToThread,那么该对象的所有槽函数就会在子线程执行(前提是,该槽函数是被信号触发的),如果直接显示调用这些槽函数,仍然会运行在原线程,不会出现多线程的效果。
  • 我们可以在一个worker类中定义多个需要做的工作(槽函数),然后触发信号,子线程就可以执行。

到了这里,关于【Qt】多线程QThread::run()与QObject::moveToThread()的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QThread: Destroyed while thread is still running——线程正在运行时销毁了线程

    QThread: Destroyed while thread is still running——线程正在运行时销毁了线程 在编写多线程程序时,可能会遇到“QThread: Destroyed while thread is still running”这个错误。这个错误表示在一个线程仍在运行时,它被销毁了。 一个常见的情况是,当一个线程正在执行某些操作时,它被强制销

    2024年02月15日
    浏览(43)
  • QT学习之旅 - QThread多线程

    其实QT中的thread(线程)是很容易的 首先是主线程 其次是一个程序 通过一个QThread来放入程序 一个简单的线程就实现了 进阶一点: 手动开启关闭线程 添加一个按键,通过 信号和槽 来控制线程使能关闭 Test不变。 现象 是 mainwindow i:99(执行完) 后窗口出现,之后 开启线程 。开启后

    2024年02月16日
    浏览(39)
  • C++ Qt开发:运用QThread多线程组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用 QThread 组件实现多线程功能。 多线程技术在程序开发中尤为常用,Q

    2024年03月09日
    浏览(46)
  • QT中Qthread线程彻底销毁的实例与注意事项(防止线程资源内存泄露)

     注意: 释放线程的时候触发线程的信号与槽连接时的连接类型参数一定要是Qt::ConnectionType::DirectConnection, 否则线程销毁不了会造成内存泄露,通过任务栏开启资源管理器可监视cup的线程数变化情况。 QThread* th=new QThread();           Work* mywork=new Work ();           mywork-move

    2024年02月02日
    浏览(42)
  • 记录opencv的 QObject::moveToThread: Current thread(...) is not the object`s thread 错误

    这个错误主要是在qt库的加载上,在安装的opencv-python工具包下有个qt文件夹,这个文件夹里面的文件估计是要来加载qt的,要是这个里面的qt库的版本和pip install pyqt5所使用的qt库的版本一样估计是没什么问题,要是不一样。就会出现核心转移的错误。(这里为什么这么说,是因

    2024年02月12日
    浏览(31)
  • 【QT5-自我学习-线程qThread练习-两种使用方式-1:通过继承线程类来使用-基础样例】

    学习线程其实有一段时间了,当时只是学习,没有实际用起来,最近做的一个qt程序,发现如果不使用线程,那么就会导致界面卡死,这样才体现出线程的实际作用。 发现卡顿的程序就是前几天说到的“【QT调用ST-link-使用QT编写程序-调用ST-LINK_CLI.exe-烧写STM32F4xxx-基础样例】”

    2024年02月11日
    浏览(34)
  • 13-1_Qt 5.9 C++开发指南_多线程及QThread 创建多线程程序_ThreadSignal

    一个应用程序一般只有一个线程,一个线程内的操作是顺序执行的,如果有某个比较消耗时间的计算或操作,比如网络通信中的文件传输,在一个线程内操作时,用户界面就可能会冻结而不能及时响应。这种情况下,可以创建一个单独的线程来执行比较消耗时间的操作,并与

    2024年02月14日
    浏览(40)
  • Qt+C++多线程thread-QThread-QTimer视频-控件动画-混合应用实例

    程序示例精选 Qt+C++多线程thread-QThread-QTimer混合应用实例 如需安装运行环境或远程调试,见文章底部个人 QQ 名片,由专业技术人员远程协助! 这篇博客针对Qt+C++多线程thread-QThread-QTimer混合应用实例编写代码,代码整洁,规则,易读。 学习与应用推荐首选。 功能:多线程thr

    2024年02月16日
    浏览(41)
  • QObject::moveToThread: Current thread(...) is not the object`s thread. Cannot move to target thread(

    最近在使用 conda 环境踩了个坑,运行 opencv 项目时弹出满屏的 Qthread 报错。 网上的解决方法大多是把 opencv-python 降级,或者 sudo 用包管理器安装到系统,但是都没有很彻底或者说优雅地解决问题。 问题描述 python 3.8 (conda) 环境下,运行 opencv 项目出现报错:QObject::moveToThread

    2024年02月11日
    浏览(48)
  • qt之movetothread理解

    qt的下线程qthread,每个线程都有自己的事件循环exec。 对象的线程上下文,每个对象都有自己的线程上下文,怎么理解呢,就是该对象在哪个线程创建,其线程上下文就是谁。 每个qobject对象在创建时都有包含线程成员,threaddata,该成员的类型是QThreadData,该成员与qobject对象

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包