Qt多线程(二)

Qt多线程(二)

     上一篇通过继承QThread类,重写run()虚函数实现多线程应用程序,这一篇通过另一种方式实现Qt的多线程应用程序编程。实现功能为线程定时器的例子。

  1)新建工程后,添加线程类MyThread,基类为QObject;

//MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H #include <QObject> class MyThread : public QObject { Q_OBJECT public: explicit MyThread(QObject *parent = 0); //线程处理函数 void myTimeout(); void setFlag(bool flag = true); signals: void mySignal(int *); public slots: private: bool bIsStop; //控制线程的启停 为真停止 }; #endif // MYTHREAD_H

 

//MyThread.cpp
#include "mythread.h" #include <QThread> #include <QDebug> MyThread::MyThread(QObject *parent) : QObject(parent) { bIsStop = false; } void MyThread::myTimeout() { static int a = 0; while(!bIsStop)
   //while(1) { a
++; QThread::sleep(1); emit mySignal(&a); qDebug()<<"子线程 id="<<QThread::currentThread(); } } void MyThread::setFlag(bool flag) { bIsStop = flag; }

 

  2)在主线程中启动子线程

//主线程头文件
#ifndef MYWIDGET_H
#define MYWIDGET_H #include <QWidget> #include "mythread.h" #include <QThread> namespace Ui { class myWidget; } class myWidget : public QWidget { Q_OBJECT public: explicit myWidget(QWidget *parent = 0); ~myWidget(); private slots: void on_startButton_clicked(); void on_stopButton_clicked(); void dealCloseWnd(); void dealSignal(int *); signals: void startThread(); //启动子线程信号,必须通过信号-槽的方式启动线程函数 private: Ui::myWidget *ui; MyThread *myT; QThread *thread; }; #endif // MYWIDGET_H

 

//主线程cpp
#include "mywidget.h" #include "ui_mywidget.h" #include <QDebug> myWidget::myWidget(QWidget *parent) : QWidget(parent), ui(new Ui::myWidget) { ui->setupUi(this); //1)动态分配空间,不能指定父对象 myT = new MyThread; //2)创建子线程 thread = new QThread(this); //3)把自定义的线程加如到子线程中 myT->moveToThread(thread); connect(myT,SIGNAL(mySignal(int*)),this,SLOT(dealSignal(int*))); qDebug()<<"主线程 id="<<QThread::currentThread();
  //4)启动线程函数信号-槽连接 connect(
this,&myWidget::startThread,myT,&MyThread::myTimeout);
connect(
this,&myWidget::destroyed,this,&myWidget::dealCloseWnd); //线程处理函数内部不允许操作图形界面 //connect的第5个参数,表示连接方式:默认是队列 ,直接 //多线程才有意义 //默认的时候,如果是多线程,默认使用队列 //如果是单线程,默认使用直接方式 //队列方式:槽函数所在的线程和接收者一样(第4个参数和第3个参数) //直接方式:槽函数所在线程和发送者一样(第4个参数和第1个线程) //通过判断类来判断是多线程还是单线程 } myWidget::~myWidget() { delete ui; } void myWidget::dealCloseWnd() { myT->setFlag(true); thread->quit(); thread->wait(); delete myT; } void myWidget::dealSignal(int *a) { //static int a = 0; //a++; ui->lcdNumber->display(*a); } void myWidget::on_startButton_clicked() { if(thread->isRunning() == true) { return; } //启动线程,但是没有启动线程处理函数 thread->start(); //不能直接调用线程处理函数 //直接调用,导致线程处理函数和主线程是在同一个线程 //myT->myTimeout(); myT->setFlag(false); emit startThread(); } void myWidget::on_stopButton_clicked() { if(thread->isRunning() == false) { return; } //通过使用flag标志控制线程停止 myT->setFlag(true); thread->quit(); thread->wait(); }

 

        需要注意:1)例子中通过使用flag标志在控制线程函数的启动和停止,如果不使用该标志位控制线程,当调用thread->quit()和thread->wait()后线程函数仍然在执行,原因是在执行thread->quit()和thread->wait()后,只用线程函数的任务处理完后,线程函数才会停止工作,而线程函数为死循环,所以会一直执行下去。同样道理在窗口关闭时也需要使用标志停止线程函数。

    2)启动线程必须使用信号-槽方式,不能直接调用线程处理函数;

    3)线程类可以定义多个函数,但是有且只能有一个线程处理函数,本例中void MyThread::myTimeout();

 

 

转载于:https://www.cnblogs.com/Forward-Forever/p/10447597.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值