Qt中的多线程

线程类QThread

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

在qt中使用了多线程,有些事项是需要额外注意的:

默认的线程在Qt中称之为窗口线程,也叫主线程(UI线程),负责窗口事件处理或者窗口控件数据的更新。

子线程负责后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给窗口线程处理。

主线程和子线程之间如果要进行数据的传递,需要使用Qt中的信号槽机制。

1.线程类QThread

QThread类提供不依赖于平台的管理线程的方法。

 Header: #include <QThread>
 qmake:  QT += core
 inherits:   QObject

QThread类的主要接口

1.1 Public Functions

 // 构造函数
 QThread(QObject* parent = Q_NULLPTR);
 ​
 // 判断线程中的任务是否处理完成
 bool isFinished() const;
 // 判断线程是否正在运行
 bool isRunning() const;
 ​
 // 返回线程的优先级
 Priority priority() const;
 // 设置线程的优先级
 void setPriority(Priority priority);
 ​
 // 退出线程的事件循环,退出码为returnCode,0表示退出成功;否则表示错误
 void exit(int returnCode = 0);
 // 阻止线程执行,直到线程结束(从run()函数返回),或等待时间超过time毫秒
 bool wait(unsigned long time = ULONG_MAX);

1.2 Public Slots

 // 退出线程的事件循环,并返回代码0,等效于exit(0)
 void quit();
 // 内部调用run()开始执行线程,操作系统根据priority参数进行调度
 void start(Priority priority = inheritPriority);
 // 终止线程的执行,但不是立即结束线程,而是等待操作系统结束线程。使用terminate()之后应使用wait()
 void terminate();

1.3 Signals

// 在线程就要结束时,发射此信号
 void finished();
 // 在线程开始执行、run()函数被调用之前发射此信号
 void started();

1.4 Static Public Members

// 返回一个指向管理当前执行线程的QThread的指针
 QThread* currentThread();
 // 返回系统上能运行的线程的理想个数
 int idealThreadCount();
 ​
 // 强制当前线程休眠msecs毫秒
 void msleep(unsigned long msecs);
 // 强制当前线程休眠secs秒
 void sleep(unsigned long secs);
 // 强制当前线程休眠usecs微秒
 void usleep(unsigned long usecs);

1.5 Protected Functions

 // 由run()函数调用,进入线程的事件循环,等待exit()退出
 int exec();
 // start()调用run()函数开始执行线程任务的执行,所以在run()函数里实现线程的任务功能
 virtual void run();

2.使用方式1

一个QThread类的对象管理一个线程,一般从QThread继承一个自定义类,并重定义run()函数,在run()函数里实现线程需要完成的任务。一般在主线程里创建工作线程,并调用start()开始执行工作线程的任务。start()函数会在内部调用run()函数,进入工作线程的事件循环,在run()函数里调用exit()或quit()可以结束线程的事件循环,或在主线程里调用terminate()强制结束线程。

2.1操作步骤

1.创建一个线程类的子类,让其继承QT中的线程类QThread

 class MyThread:public QThread
 {
     ......
 }

2.重写QThread类的run()方法,在该函数内部编写子线程要处理的具体的业务流程

 class MyThread:public QThread
 {
     ......
     protected:
         void run()
         {
             ......
         }
 }

3.在主线程中创建子线程对象

4.启动子线程,调用start()方法

3.使用方式2

3.1操作步骤

1.创建一个工作类,让这个类从QObject派生

class MyWork : public QObject
 {
     ......
 }

2.在这个类中添加一个公共的成员函数,函数体就是我们要子线程中执行的业务逻辑

class MyWokr : public QObject
 {
     public:
         ......
         // 工作函数
             void working();
 }

3.在主线程中创建一个QThread对象,这个就是子线程的对象

 QThread* sub = new QThread;

4.在主线程中创建工作的类对象(不能指定给创建的对象指定父对象)

 MyWork* work = new MyWork;

5.将MyWork对象移动到创建的子线程中,需要调用QObject类提供的moveToThread()方法

 work->moveToThread(sub);

6.启动子线程,调用start(),这个时候线程启动了,但是移动到线程中的对象并没有工作

7.调用MyWork类对象的工作函数,让这个函数开始执行,这个时候是在移动到的内个子线程中运行的

4.释放资源

1.方法1

给创建的线程类QThread指定父对象。由Qt的对象树机制,自动回收资源。

2.方法2

通过信号槽来回收资源。当当前窗口析构时会发出信号:destroyed()。

 connect(this, &MainWindow::destroyed, this, [=]()
         {
             thread->quit();
             thread->wait();
             thread->deleteLater();
         });

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值