欢迎您访问系统网
您现在的位置是:首页» windows系统» qt多线程和c++多线程哪个好些,qt创建线程的几种方法

qt多线程和c++多线程哪个好些,qt创建线程的几种方法

2023-12-05 05:13:42
今天小编为大家分享Windows系统下载、Windows系统教程、windows相关应用程序的文章,希望能够帮助到大家! 多线程对于需要处理耗时任务的应用很有用,一方面响应用户操作、更新界面显示,另一方面在“后台”进行耗时操作,比如大量运算、复制大文件、网络传输等。使用Qt框架开发应用程序时,使用QThr

今天小编为大家分享Windows系统下载、Windows系统教程、windows相关应用程序的文章,希望能够帮助到大家!

多线程对于需要处理耗时任务的应用很有用,一方面响应用户操作、更新界面显示,另一方面在“后台”进行耗时操作,比如大量运算、复制大文件、网络传输等。

使用Qt框架开发应用程序时,使用QThread类可以方便快捷地创建管理多线程。而多线程之间的通信也可使用Qt特有的“信号-槽”机制实现。

下面的说明以文件复制为例。主线程负责提供交互界面,显示复制进度等;子线程负责复制文件。最后附有可以执行的代码。

2. QThread使用方法1——重写run()函数

第一种使用方法是自己写一个类继承QThread,并重写其run()函数。

大家知道,C/C++程序都是从main()函数开始执行的。main()函数其实就是主进程的入口,main()函数退出了,则主进程退出,整个进程也就结束了。

而对于使用Qthread创建的进程而言,run()函数则是新线程的入口,run()函数退出,意味着线程的终止。复制文件的功能,就是在run()函数中执行的。

下面举个文件复制的例子。自定义一个类,继承自Qthread

CopyFileThread: public QThread

CopyFileThread(QObject* parent= 0);protected: void run();//新线程入口//省略掉一些内容}

void CopyFileThread::run(){//新线程入口

将这个类写好之后,在主线程的代码中生成一个CopyFileThread的实例,例如在mainwindow.cpp中写:

// mainwindow.h中CopyFileThread* m_cpyThread;// mainwindow.cpp中m_cpyThread= new CopyFileThread;

在要开始复制的时候,比如按下“复制”按钮后,让这个线程开始执行:

注意,使用start()函数来启动子线程,而不是run()。start()会自动调用run()。

线程开始执行后,就进入run()函数,执行复制文件的操作。而此时,主线程的显示和操作都不受影响。

如果需要进行对复制过程中可能发生的事件进行处理,例如界面显示复制进度、出错返回等等,应该从CopyFileThread中发出信号(signal),并事先连接到mainwindow的槽,由这些槽函数来处理事件。

3. QThread使用方法2——moveToThread()

如果不想每执行一种任务就自定义一个新线程,那么可以自定义用于完成任务的类,并让它们继承自QObject。例如,自定义一个FileCopier类,用于复制文件。

class FileCopier: public QObject

Q_OBJECTpublic: explicit FileCopier(QObject*parent= 0);public slots: void startCopying(); void cancelCopying();

注意这里我们定义了两个槽函数,分别用于复制的开始和取消。

这个类本身的实例化是在主线程中进行的,例如:

FileCopier* m_copier;// mainwindow.cpp中,初始化时

此时m_copier还是属于主线程的。要将其移动到子线程处理,需要首先声明并实例化一个QThread:

// mainwindow.h中signals: void startCopyRsquested();private:

QThread* m_childThread;// m_copier将被移动到此线程执行// mainwindow.cpp中,初始化时

m_childThread= new QThread;//子线程,本身不负责复制

然后使用moveToThread()将m_copier移动到新线程。注意moveToThread()是QObject的公有函数,因此用于复制文件的类FileCopier必须继承自QObject。移动之后启动子线程。此时复制还没有开始。

m_copier->moveToThread(m_childThread);//将实例移动到新的线程,实现多线程运行

m_childThread->start();//启动子线程

注意一定要记得启动子线程,否则线程没有运行,m_copier的功能也无法执行。

要开始复制,需要使用信号-槽机制,触发FileCopier的槽函数实现。因此要事先定义信号并连接:

// mainwindow.h中signals: void startCopyRsquested();// mainwindow.cpp中,初始化时//使用信号-槽机制,发出开始指令

connect(this, SIGNAL(startCopyRsquested()), m_copier, SLOT(startCopying()));

当按下“复制”按钮后,发出信号。

emit startCopyRsquested();//发送信号

m_copier在另一个线程接收到信号后,触发槽函数,开始复制文件。

4.1.子线程中能不能进行UI操作?

Qt中的UI操作,比如QMainWindow、QWidget之类的创建、操作,只能位于主线程!

这个限制意味着你不能在新的线程中使用QDialog、QMessageBox等。比如在新线程中复制文件出错,想弹出对话框警告?可以,但是必须将错误信息传到主线程,由主线程实现对话框警告。

因此一般思路是,主线程负责提供界面,子线程负责无UI的单一任务,通过“信号-槽”与主线程交互。

4.2. QThread中的哪些代码属于子线程?

QThread,以及继承QThread的类(以下统称QThread),他们的实例都属于新线程吗?答案是:不。

需要注意的是,QThread本身的实例是属于创建该实例的线程的。比如在主线程中创建一个QThread,那么这个QThread实例本身属于主线程。当然,QThread会开辟一个新线程(入口是run()),但是QThread本身并不属于这个新线程。也就是说,QThread本身的成员都不属于新线程,而且在QThread构造函数里通过new得到的实例,也不属于新线程。这一特性意味着,如果要实现多线程操作,那么你希望属于新线程的实例、变量等,应该在run()中进行初始化、实例化等操作。本文给出的例子就是这样操作的。

如果你的多线程程序运行起来,会出现关于thread的报警,思考一下,各种变量、实例是不是放对了位置,是不是真的位于新的线程里。

4.3.怎么查看是不是真的实现了多线程?

可以打印出当前线程。对于所有继承自QObject的类,例如QMainwindow、QThread,以及自定义的各种类,可以调用QObject::thread()查看当前线程,这个函数返回的是一个QThread的指针。例如用qDebug()打印:

在mainwindow.cpp的某个函数里、QThread的run()函数里、自定义类的某个函数里,写上:

qDebug()<<"Current thread:"<< thread();

对比不同位置打印的指针,就可以知道它们是不是位于同一个线程了。

范例实现了多线程复制文本文件。

提供的范例文件可用QtCreator编译运行。界面如下(不同的操作系统略有不同):

范例中实现了本文介绍的两种方法,同时也给出了单线程复制对比。打钩选择不同的复制方法。可以发现,在使用多线程的时候,界面不会假死,第二根进度条的动画是持续的;而使用单线程复制的时候,“取消”按钮按不动,界面假死,而且第二根进度条的动画也停止了。

由于范例处理的文件很小,为了让复制过程持续较长时间以便使得现象明显,复制文件的时候,每复制一行加入了等待。

github.com/Xia-Weiwen/CopyFile

1、在Qt中使用多线程,目前就我使用过的有两种,一是子类化QThread,重写run函数,在run函数里实现自己的代码,这一部分代码通常是比较耗时,或者干脆直接阻塞的。比如一个while循环,设置一个标志,判断循环结束。

2、这样的例子在网上有很多,就不写了。

3、这样写的话,会有一些东西需要了解。

4、子类化QThread的方法,只有run函数里面的内容是执行在子线程里的,其他的部分,比如槽函数什么的还是在主线程里执行(假设是在主线程开启的该子线程)。

5、还有一种方法,是子类化QObject,新建一个线程,然后使用MoveToThread把这个类的对象移到新建的线程中,这种做法使得它所有的槽函数都是执行在新开辟的线程里面。

6、如果直接(QObject对象).abc()的话,这个成员函数是在主进程内执行,可能会出现"QObject::killTimer: timers

7、cannot be stopped from another thread"的运行错误。

8、使用第二种方法的话,貌似会遇到这样的问题:如果在一个槽函数中把子线程阻塞,其他的槽函数无法接受来自主线程

wwW.Xtw.Com.cN系统网专业的PC、手机系统开发下载平台,HarmonyOS系统、安卓、OS、windows电脑重装系统在线下载安装,操作系统平台技术学习,攻略教程,技术交流。

免责声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。内容仅供参考使用,不准确地方联系删除处理!

联系邮箱:773537036@qq.com

标签: 多线程 创建 qt