QT创建线程的方法:一步步教你创建和启动线程

这篇具有很好参考价值的文章主要介绍了QT创建线程的方法:一步步教你创建和启动线程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

线程概念及官方文档

 一、线程的创建:继承方式

二、线程的创建:QObject 对象(moveToThread)

2.1 创建任务类

2.2 添加线程启动(定时器启动)

2.3 添加线程启动(start信号启动)

三、线程类的基本接口和使用

3.1启动 和终止线程

3.2 线程延迟

3.3 线程同步及通信方式

3.4 常用函数例举

四、线程释放

五、总结

线程概念及官方文档

        线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。这段话摘之网络。

        从下面的官方文档可以看出,如果一个线程类要支持信号和槽,那么,该类要直接或者间接的继承于QObject类,并且在类中要声明宏:Q_OBJECT

        好了,不说概念了,不喜欢说概念,直接开始说干货。

qt 创建线程,QT开发,c++,qt,windows

 一、线程的创建:继承方式

线程的创建方式:自定义一个类继承于QThread,并且 重写该类的run函数,run函数中,就是 子线程要执行任务。在创建线程后,要进行启动线程 操作,下面是例子

class WorkerThread : public QThread
{
      
      void run() override { 
          while(1){
              qDebug()<<"hello";
              QThread::sleep(1);
            }
      }
 
};

运用的话简单,举个例子,就能看到一秒中输出一次 hello

 WorkerThread *workerThread = new WorkerThread(this);
 workerThread->start();//子线程要调用start启动,否则,不会执行

注意事项:

      1. 默认情况下,void run() 只执行一次,想要执行多次,要手动使用循环语句

      2. 子线程一定要调用start启动,否则,不会执行

      3.要想实现和其他线程通信,可使用信号的方式进行通信,后面我上传 缓冲区那篇文章会用到。

     实现的步骤基本就是

1.创建一个子类继承于QThread,并且重写run函数
2.创建子线程对象
3.启动子线程 ---- start()

二、线程的创建:QObject 对象(moveToThread)

这种方式我重点讲,前面的方式对于我来说,没有这种方式好用,在开发中,我经常用这种方式。

步骤分为三步,第一步创建用于运行任务的类,第二步创建线程,并在类中添加线程,第三步启动

下面讲一下详细步骤。

2.1 创建任务类

创建一个类继承于QObject,并且声明Q_OBJECT,这是规定的。定义一个槽函数,用于线程的执行。下面用代码演示一下

class threadhid : public QObject
{
    Q_OBJECT
public:
    explicit threadhid(QObject *parent = nullptr);
    ~threadhid();
  void stopRun(void);   //用于退出
 
public:
   bool m_Run ;      //退出线程的标志位

public slots:
  void Receive();    //用于线程循环

};

函数实现:

这是最简单的模板,具体的功能可以自己添加上去。简单说明一下参数,m_Run标志位是为了更好的退出这个槽函数,再释放线程。stopRun()函数是可以通过类接口进行释放线程,更加安全,不会随意退出,更好管理。

threadhid::threadhid(QObject *parent ): QObject(parent)
{
   
}
threadhid::~threadhid()
{

}
void threadhid::stopRun(void)
{
    m_bRun = false;
}
void threadhid::Receive()
{
     
      m_Run = true;
      while(true) {


          if(!m_Run)
          {
             qDebug()<<"退出";
             break;
          }
   
           QThread::msleep(200);
           qDebug()<<"hello 大宝犯疆土...";
              
      }

}

2.2 添加线程启动(定时器启动)

 上面是创建任务,现在是给与这个类一个线程,达到分离的效果。

  第一步创建类线程

 QThread * thread_Hid = new QThread;         
  第二步创建任务类
 threadhid*  USB_Handle = new threadhid() ;  //创建任务类

第三步添加到线程中

USB_Handle->moveToThread(&thread_Hid); 

第四步 线程释放  

 connect(&thread_Hid, &QThread::finished, USB_Handle, &QObject::deleteLater);

注:这段代码是用于连接一个线程对象 thread_Hid 的 finished() 信号和一个 QObject 对象 USB_Thread 的 deleteLater() 槽函数的。 在多线程编程中,线程的生命周期可能会比较复杂,如果没有正确地管理线程的生命周期,就可能会导致内存泄漏或者程序崩溃等问题。因此,Qt 提供了一些机制来帮助管理线程的生命周期,其中之一就是通过在线程结束时自动删除线程对象来确保线程对象的正确释放。 在上述代码中,当 thread_Hid 线程结束时,就会发出 finished() 信号,这个信号被连接到 USB_Thread 对象的 deleteLater() 槽函数上,这样当线程结束时,就会自动调用 USB_Thread 对象的 deleteLater() 槽函数,从而保证线程对象的正确释放。 需要注意的是,当使用 QObject::deleteLater() 槽函数时,要确保所要删除的对象是在其所属线程的事件循环中被创建的,否则 deleteLater() 函数可能不会生效。

第五步 线程启动

thread_Hid.start();

第六步 创建单次定时器启动线程任务

timerHid = new QTimer(this);

connect(timerHid, &QTimer::timeout, USB_Handle, &threadhid::Receive);

timerHid->setSingleShot(true);

timerHid->start(1000);

为了方便大家复制和我以后某一天想起,直接贴完整代码

 threadhid*  USB_Handle = new threadhid() ;  
 
 QThread * thread_Hid = new QThread;   //线程
   USB_Handle->moveToThread(&thread_Hid);添加到线程中
   //线程释放
   connect(&thread_Hid, &QThread::finished, USB_Handle, &QObject::deleteLater);
     
   thread_Hid.start();//线程启动
   
   //定时器单次运行
    timerHid = new QTimer(this);
     connect(timerHid, &QTimer::timeout, USB_Handle, &threadhid::Receive);
     timerHid->setSingleShot(true);
     timerHid->start(1000);

2.3 添加线程启动(start信号启动)

为什么说这个呢,就是想简单的记录一下多种启动方式,上面的那种是我自己用的,我觉得可以让时间更加可靠,而下面这种是一启动就运行的。2.3和2.2效果是一样,不用重复写。

connect(thread_Hid, &QThread::started, USB_Handle, &threadhid::Receive); // 连接线程槽

thread_Hid->start();       //启动

三、线程类的基本接口和使用

3.1启动 和终止线程

3.1.1退出线程

void quit() //退出一个线程循环,可以起作 停止线程

3.1.2 启动线程

start(QThread::Priority priority = InheritPriority)//启动线程

3.1.3 退出线程

terminate()//终止线程

区别:

terminate() 函数是一个强制终止程序的函数,它可以立即终止应用程序并释放相关资源,但这种方式可能会导致一些未定义的行为,例如可能会导致未处理的异常和内存泄漏等问题。因此,建议只在出现紧急情况时使用 terminate() 函数。

quit() 函数是一个优雅地终止程序的函数,它会告诉事件循环停止运行,并等待所有线程结束后再退出应用程序。它会释放所有的资源,包括 GUI 界面等。因此,建议在正常情况下使用 quit() 函数来终止应用程序。

3.2 线程延迟

qt 创建线程,QT开发,c++,qt,windows

3.3 线程同步及通信方式

同步机制的目的是为了保护数据或者代码段,在多线程中,每次只允许一个线程来进行访问。线程同步方式:互斥锁 读写锁 信号量等

QMutex、QMutexLocker, QReadWriteLock, QSemaphore, and QWaitCondition.具体用法就不说了,复制一下百度,这次重点介绍线程。

通信方式:

1.信号和槽 

2.QMetaObject::invokeMethod():可以在不同线程之间异步地调用一个函数,实现线程间的通信。

3.QThread::event()和QCoreApplication::postEvent():可以用于在线程之间发送事件和处理事件。

3.4 常用函数例举

  1. start() 函数:用于启动线程,它会调用线程的 run() 函数,并将线程标记为“运行中”。

  2. run() 函数:是线程的主函数,可以在该函数中执行需要在线程中运行的代码。

  3. wait() 函数:用于等待线程结束,它会使当前线程阻塞,直到目标线程结束为止。

  4. quit() 函数:用于终止线程,它会发送一个退出信号给线程,并等待线程结束后才返回。

  5. isRunning() 函数:用于检查线程是否正在运行中。

  6. setPriority() 函数:用于设置线程的优先级,Qt 支持以下几种优先级:IdlePriority、LowestPriority、LowPriority、NormalPriority、HighPriority、HighestPriority、TimeCriticalPriority。

  7. sleep() 函数:用于使当前线程睡眠一段时间,单位是毫秒。

  8. msleep() 函数:用于使当前线程睡眠一段时间,单位是微秒。

  9. yieldCurrentThread() 函数:用于将 CPU 时间让给其他线程。

  10. currentThreadId() 函数:用于获取当前线程的 ID。

  11. event() 函数:用于处理事件,QThread 中的事件有两种:QThread::CustomEventType 和 QThread::Quit。

  12. exit() 函数:用于退出线程,并释放线程所占用的资源。

  13. finished() 信号:当线程结束时会发出该信号,可以通过该信号来实现线程的清理工作。

需要注意的是,在多线程编程中,要避免使用一些不安全的操作,如访问全局变量、使用未初始化的指针、使用不可重入的函数等,否则可能会导致程序出现不可预知的错误。在多线程编程中需要特别注意线程安全问题。

四、线程释放

线程的释放也是跟重要的,作为一个合格的工程师不能只管申请不管释放,有始有终对吧。

第一步释放类内资源,并退出死循环

第二步退出事件循环

第三步等待线程退出

第四步释放内存

    USB_Handle->stopRun(); //先退出死循环 m_Run = false;
    thread_Hid.quit(); //退出事件循环
    thread_Hid.wait(); //等待线程退出
   // QThread::terminate()//也可以,但是上面的方式更加温柔

    delete  thread_Hid;
    delete USB_Handle ;

大功告成。

五、总结

  • QThread 可以通过继承 QThread 类并重写 run 函数来实现自定义线程类。
  • QThread 还提供了信号槽机制,使得线程之间的通信更加方便。
  • QThread 通过 exec 函数实现事件循环,当线程没有事件时,exec 函数会阻塞线程。

注意事项:

  • QThread 中创建的对象默认情况下都会与 QThread 线程关联,应该使用 moveToThread 函数将其移动到新的线程中。
  • 不应该直接调用 QThreadrun 函数,应该通过 start 函数来启动线程。
  • QThread 对象应该在主线程中创建,并且只能在主线程中删除。
  • 为了避免资源泄露,应该在线程执行完毕后将其删除。

Qt线程的总结暂时就这么多,我写的博客偏向于实际应用型,概念不多强调,只为更加方便的使用,减少废话。如果本篇给与你开发或多或少的帮助,希望可以给个点赞激励一下哈。文章来源地址https://www.toymoban.com/news/detail-538533.html

到了这里,关于QT创建线程的方法:一步步教你创建和启动线程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Qt进行UDP通讯,创建一个收线程这样可以进行接收数据

    Qt进行UDP通讯,创建一个收线程这样可以进行接收数据

    在.pro中增加一句话 绘制界面 .h文件内容: 构造函数内容 对于绑定按钮的定义函数: 接收信号的槽函数(UDP接收到数据显示) quitThreaSlot函数: 退出按钮定义: 使用的receivethread.h就是将run函数重写(循环发送定义的信号延迟即可),在定义一个信号即可。 以上即功能的所有

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

    C++ Qt开发:运用QThread多线程组件

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

    2024年03月09日
    浏览(34)
  • 【Qt】QThread & moveTothread-多线程的两种实现方法

    【Qt】QThread & moveTothread-多线程的两种实现方法

    一、如何理解多线程 二、实现多线程的两种方式(面向应用) 2.1 继承 QThread 的类 2.2 (推荐这种方式)函数 moveTothread() 三、多线程的释放问题(善后工作) 类似我们单片机的编程,如在 Keil5 中对 51 单片机或者 STM32 单片机进行编程时,如果我们使用模块化编程,那么 main.c 文

    2024年02月01日
    浏览(9)
  • 【QT】C++和QML使用多线程优化界面切换卡顿的方法

    【QT】C++和QML使用多线程优化界面切换卡顿的方法

    qt提供了一种声明式语言qml,可以使用一些可视组件以及这些组件之间的交互来描述用户界面,而c++可以只负责后台逻辑的处理,将界面和后台分离开来,由qml来做UI界面,c++负责后端处理,对我个人来说,这样的方式大大的方便了对界面和逻辑的修改和维护; 由于UI界面是工

    2024年01月19日
    浏览(10)
  • 一步步教你在 Windows 上构建 dotnet 系应用的 UOS 软件安装包

    一步步教你在 Windows 上构建 dotnet 系应用的 UOS 软件安装包

    本文将详细指导大家如何逐步为 dotnet 系列应用创建满足 UOS 统信系统软件安装包的要求。在这里,我们所说的 dotnet 系列应用是指那些能够在 Linux 平台上构建 UI 框架的应用,包括但不限于 CPF 应用、UNO 应用、Avalonia 应用等 基于 dotnet 系的自发布自包含的能力,可以将 dotnet

    2024年04月26日
    浏览(7)
  • 使用Qt Designer为您的Qt for Python项目创建基于Qt Widgets的图形界面的两种方法

    使用Qt Designer为您的Qt for Python项目创建基于Qt Widgets的图形界面的两种方法

    本页介绍如何使用Qt Designer为您的Qt for Python项目创建基于Qt Widgets的图形界面。Qt Designer是一个图形UI设计工具,可以作为独立的二进制文件(pyside6-designer)提供,也可以嵌入到Qt Creator IDE中。它在Qt Creator中的使用在Using Qt Designer中描述。 设计存储在.ui文件中,这是一种基于

    2024年02月07日
    浏览(11)
  • 迅为RK3568开发板Buildroot 系统自启动 QT 程序

    迅为RK3568开发板Buildroot 系统自启动 QT 程序

    本小节将讲解如何开机自启动 QT 程序。 在设置自启动 QT 程序之前,首先要编译好 QT 可执行程序,完成以下两步。 1、 已经根据 03_【北京迅为】itop-3568 开发板快速使用编译环境 ubuntu18.04 v1.0.doc 第 10 章节进行了 QT 程序的交叉编译 2、 将交叉编译出的 QT 可执行程序拷贝到/u

    2024年02月12日
    浏览(43)
  • Windows下的QT系统开发环境搭建

    Windows下的QT系统开发环境搭建

            QT是一款由Qt Company开发的跨平台C++图形用户界面 应用程序 开发框架。它既可以开发 GUI 程序,也可用于开发非GUI程序,比如 控制台 工具和服务器。Qt是面向对象的框架,使用特殊的 代码 生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容

    2024年02月09日
    浏览(12)
  • QGIS开发五:VS使用QT插件创建UI界面

    QGIS开发五:VS使用QT插件创建UI界面

    前面我们说了在创建项目时创建的是一个空项目,即不使用 Qt 提供的综合开发套件 Qt Creator,也不使用 Qt Visual Studio Tools 这类工具。 但是后面发现,如果我想要有更加满意的界面布局,还是要自己写一个UI文件,如果不使用QT插件,在VS中导入自己的UI文件编译起来不是那么容

    2024年02月13日
    浏览(11)
  • Qt Creator启动后卡死无响应的解决方法(已解决)

    我的是 有道云词典屏幕取词会与QtUI进程产生冲突 ,我关掉了有道云词典的取词功能,则正常了。 参考这位博客,他还讲了其它的一些可能原因:QTCreator打开无响应问题_qt creator卡死_我对世界嗤之以鼻的博客-CSDN博客 如果 Qt Creator启动速度特别慢,可以看我这个博客:Qt Cr

    2024年02月14日
    浏览(13)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包