Qt的4种多线程实现方式

Qt的4种多线程实现方式一 QThread 类的 run 一 实现方法 新建一个集成 QThread 的类 重写虚函数 run 通过 run 启动线程二 示例 include QThread include QDebug classMyThrea publicQThrea Q OBJECTprotec voidrun dosomethingq lt lt FUNCTION lt amp QDebug QThread

一、QThread类的run

一、实现方法:

新建一个集成QThread的类,重写虚函数run,通过run启动线程

二、示例:

 class WorkerThread : public QThread { Q_OBJECT void run() override { QString result; /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } signals: void resultReady(const QString &s); }; void MyObject::startWorkInAThread() { WorkerThread *workerThread = new WorkerThread(this); connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults); connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater); workerThread->start(); }

三、特点:

二、QThread类的moveToThread

一、实现方法:

创建一个继承QObject的类(myobject),然后new一个Qthread,并把创建的myobject类movetothread到创建好的子线程中,然后start子线程,这样就实现了一个子线程。主线程通过发送信号,调用myobject中的方法,从而实现在子线程中的计算。

二、示例:

 class Worker : public QObject { Q_OBJECT public slots: void doWork(const QString &parameter) { QString result; /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } signals: void resultReady(const QString &result); }; class Controller : public QObject { Q_OBJECT QThread workerThread; public: Controller() { Worker *worker = new Worker; worker->moveToThread(&workerThread); connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); connect(this, &Controller::operate, worker, &Worker::doWork); connect(worker, &Worker::resultReady, this, &Controller::handleResults); workerThread.start(); } ~Controller() { workerThread.quit(); workerThread.wait(); } public slots: void handleResults(const QString &); signals: void operate(const QString &); };

三、特点:

MovetoThreadTest.cpp 中用到了窗体中的几个按钮,在如用代码是首相创建一个窗体,在窗体添加按钮,然后跟据按钮的名字进行连接即可;

主线程如果要在子线程中运行计算必须通过发信号的方式调用,或者通过控件的信号;需要说明在创建连接时如果第五的参数为DirectConnection时,调用的槽函数是在主线程中运行;如果想通过子线程向主线程调用方法,也必须通过发信号的方式触发主线程的函数。

Qt::AutoConnection,t::DirectConnection,t::QueuedConnection,t::BlockingQueuedConnection,t::UniqueConnection

Qt::AutoCompatConnection这里面一共有六种方式。

moveToThread对比传统子类化Qthread更灵活,仅需要把你想要执行的代码放到槽,movetothread这个object到线程,然后拿一个信号连接到这个槽就可以让这个槽函数在线程里执行。可以说,movetothread给我们编写代码提供了新的思路,当然不是说子类化qthread不好,只是你应该知道还有这种方式去调用线程。

轻量级的函数可以用movethread,多个短小精悍能返回快速的线程函数适用 ,无需创建独立线程类,例如你有20个小函数要在线程内做, 全部扔给一个QThread。而我觉得movetothread和子类化QThread的区别不大,更可能是使用习惯引导。又或者你一开始没使用线程,但是后边发觉这些代码还是放线程比较好,如果用子类化QThread的方法重新设计代码,将会有可能让你把这一段推到重来,这个时候,moveThread的好处就来了,你可以把这段代码的从属着movetothread,把代码移到槽函数,用信号触发它就行了。其它的话movetothread它的效果和子类化QThread的效果是一样的,槽就相当于你的run()函数,你往run()里塞什么代码,就可以往槽里塞什么代码,子类化QThread的线程只可以有一个入口就是run(),而movetothread就有很多触发的入口。

 

三、QRunnalble的run

Qrunnable是所有可执行对象的基类。我们可以继承Qrunnable,并重写虚函数void QRunnable::run () 。我们可以用QThreadPool让我们的一个QRunnable对象在另外的线程中运行,如果autoDelete()返回true(默认),那么QThreadPool将会在run()运行结束后自动删除Qrunnable对象。可以调用void QRunnable::setAutoDelete ( bool autoDelete )更改auto-deletion标记。需要注意的是,必须在调用QThreadPool::start()之前设置,在调用QThreadPool::start()之后设置的结果是未定义的。

一、实现方法:

1、继承QRunnable。和QThread使用一样, 首先需要将你的线程类继承于QRunnable。

2、重写run函数。还是和QThread一样,需要重写run函数,run是一个纯虚函数,必须重写。

3、使用QThreadPool启动线程

二、示例:

class Runnable:public QRunnable { //Q_OBJECT 注意了,Qrunnable不是QObject的子类。 public: Runnable(); ~Runnable(); void run(); }; Runnable::Runnable():QRunnable() { } Runnable::~Runnable() { cout<<"~Runnable()"<<endl; } void Runnable::run() { cout<<"Runnable::run()thread :"<<QThread::currentThreadId()<<endl; cout<<"dosomething ...."<<endl; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); cout<<"mainthread :"<<QThread::currentThreadId()<<endl; Runnable runObj; QThreadPool::globalInstance()->start(&runObj); returna.exec(); } 

四、QtConcurrent的run

Concurrent是并发的意思,QtConcurrent是一个命名空间,提供了一些高级的 API,使得在编写多线程的时候,无需使用低级线程原语,如读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器内核数自动调整使用的线程数。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展。

QtConcurrent::run能够方便快捷的将任务丢到子线程中去执行,无需继承任何类,也不需要重写函数,使用非常简单。详见前面的文章介绍,这里不再赘述。

需要注意的是,由于该线程取自全局线程池QThreadPool,函数不能立马执行,需要等待线程可用时才会运行。

一、实现方法:

1、首先在.pro文件中加上以下内容:QT += concurrent

2、包含头文件#include ,然后就可以使用QtConcurrent了

QFuture<void> fut1 = QtConcurrent::run(func, QString(“Thread 1”));  fut1.waitForFinished();

二、示例:

#include <QtCore/QCoreApplication> #include <QDebug> #include <QThread> #include <QString> #include <QtConcurrent/QtConcurrentRun> #include <QTime> #include<opencv2\opencv.hpp> #include"XxwImgOp.h" #ifdef _DEBUG #pragma comment(lib,".\\XxwImgOpd.lib") #else #pragma comment(lib,".\\XxwImgOp.lib") #endif // _DEBUG using namespace QtConcurrent; XxwImgOp xxwImgOp; cv::Mat src = cv::imread("1.bmp", 0); cv::Mat dst, dst1, dst2; void hello(cv::Mat src) { qDebug() << "-----------" << QTime::currentTime()<<"------------------------"<<QThread::currentThreadId(); xxwImgOp.fManualThreshold(src, dst, 50, 150); qDebug() <<"" << QTime::currentTime() <<""<< QThread::currentThreadId(); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QFuture<void> f1 = run(hello, src); QFuture<void> f2 = run(hello, src); //阻塞调用,阻塞主线程直到计算完成 f1.waitForFinished(); f2.waitForFinished(); //阻塞为End的执行顺序 qDebug() << "End"; return a.exec(); }

 

三、特点:

//调用外部函数 QFuture<void> f1 =QtConcurrent::run(func,QString(“aaa”));

//调用类成员函数 QFuture<void> f2 =QtConcurrent::run(this,&MainWindow::myFunc,QString(“bbb”));

要为其指定线程池,可以将线程池的指针作为第一个参数传递进去

向该函数传递参数,需要传递的参数,则跟在函数名之后

 缺点,不能直接用信号和槽函数来操作线程函数,eg : 当线程函数结束时,不会触发任何信号。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232083.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 嵌入式实时操作系统UCOSII[通俗易懂]

    嵌入式实时操作系统UCOSII[通俗易懂]何谓操作系统1.什么是操作系统?操作系统是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行。介于APP和硬件之间。2. 为什么要用操作系统?1)相比裸机,可以实现更加复杂的功能。2)屏蔽硬件。使得上层应用APP的移植性更好。常见操作系统常见操作系统安卓、IOS、Windows、Linux、塞班、V…

    2022年5月4日
    167
  • linux抓包命令tcpdump 文本,Linux下抓包命令tcpdump的使用

    linux抓包命令tcpdump 文本,Linux下抓包命令tcpdump的使用在linux下,可以使用tcpdump命令来抓取数据包。主要用法如下:过滤网卡tcpdump-ieth0#抓取所有经过网卡eth0数据包tcpdump-ilo#抓取环回口的数据包过滤主机/IPtcpdumphost192.168.10.10#抓取所有IP为192.168.10.10的数据包tcpdumpsrchost192.168.10…

    2022年6月26日
    31
  • softmax 损失函数与梯度推导「建议收藏」

    softmax 损失函数与梯度推导「建议收藏」softmax与svm很类似,经常用来做对比,svm的lossfunction对wx的输出s使用了hingefunction,即max(0,-),而softmax则是通过softmaxfunction对输出s进行了概率解释,再通过crossentropy计算lossfunction。将score映射到概率的softmaxfunction:,其中,,j指代i-thclass。…

    2022年6月26日
    66
  • cheerio 笔记

    cheerio 笔记简介 cheerio 是一个 node 的库 可以理解为一个 Node js 版本的 jquery 用来从网页中以 cssselector 取数据 使用方式和 jquery 基本相同 npminstallch require cheerio var cheerio load lt h2class title gt Hellowo

    2025年11月20日
    2
  • Vue的基本模板

    Vue的基本模板<!–1.Vue框架使用方式1.1传统下载导入使用1.2vue-cli安装导入使用2.Vue框架使用步骤2.1下载Vue框架2.2导入Vue框架2.3创建Vue实例对象2.4指定Vue实例对象控制的区域2.5指定Vue实例对象控制区域的数据–><!DOCTYPEhtml><htmllang=”en”><head><metacharset=”UTF-8″><title>02-Vu

    2022年7月24日
    13
  • latex中希腊字母_LaTeX符号

    latex中希腊字母_LaTeX符号Latex和Matlab绘图中希腊字母、特殊符号汇总表Latex和Matlab绘图中希腊字母、特殊符号汇总表Latex和Matlab绘图中希腊字母、特殊符号汇总表一、小写希腊字母、特殊符号二、大写希腊字母三、希腊字母斜体原创不易,路过的各位大佬请点个赞一、小写希腊字母、特殊符号二、大写希腊字母三、希腊字母斜体原创不易,路过的各位大佬请点个赞…

    2022年10月13日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号