16、多线程

1、qt4.7以前版本处理方式,多线程的使用

  1、多线程使用模板:

  1、自定义一个类,继承于QThread,

class MyThread : public QThread
{
    publicvoid run();     // 多任务执行函数
   
    signals:
        void isDone();   // 处理完成后需要发送信号需要知道,线程处理完成任务
}
void run()   // 函数实现
{
    // 处理复杂任务
   // 发送信号  任务处理完成
    emit isDone();
}

    

  2、使用的地方需要创建一个类对象

MyThread thread;


// 在需要多任务的地方启动线程
// 不可以直接掉用run()
// start() 间接调用run()

thread.start();   // 启动线程

3、线程使用

  2、多线程简单使用例子

  Step 1、创建一个类继承QThread

#include <QThread>

class myThread : public QThread
{

protected:
    void run();  // 重写虚函数 线程的入口函数
signals:
    void isDone();  // 发信号 说明线程结束了
};

  Step 2、实现run()函数

void myThread::run()
{
    qDebug() << ";正在睡觉";
    sleep(5);   // 任务处理代码
    emit isDone();  // 发送信号 说明该线程结束了
}

  Step 3、线程启动,转去执行run()

void Widget::on_buttonStart_clicked()
{
    if(myTimer->isActive() == false)
    {
        myTimer->start(100);
    }
    // 需要多线程的地方 启动线程
    thread->start();   // 启动线程
}

  Step 4、等待run()发出线程结束信号,并处理信号

thread = new myThread(this);
// 处理线程结束信号标志
connect(thread,&myThread::isDone,this,&Widget::dealPmythread);

  Step 5、线程结束处理

void Widget::dealPmythread()
{
    qDebug() << "deal over";
    myTimer->stop();   // 线程结束了 进一步处理
}

  Step 6、释放线程资源

// 窗口右上角X 关闭时,发出信号处理, 释放线程资源
    connect(this,&Widget::destroyed,this,&Widget::closeThread);

  Step 7、释放线程 函数实现

void Widget::closeThread()
{
    thread->quit();   // 关闭线程
    thread->wait();   // 等待线程处理完资源
}

 4、比较方便的使用多线程 线程使用框图

  1、设定一个类,继承于QObject

  2、类中设置一个线程函数(只有一个是线程函数)

  使用的全部代码

#include <QObject>
#include <QThread>

class myTHread : public QObject
{
    Q_OBJECT
public:
    void mytimeout();   // 处理多任务的函数
    bool isStop = false;  


signals:
    void mysignal();   // 多任务处理完成发送的信号

};

#endif // MYTHREAD_H

// 任务处理函数实现

// 需要多任务处理的函数
void myTHread::mytimeout()
{
    while(isStop == false)  //  结束时可以停止线程
    {
        if(isStop == true)
        {
           break;
        }
        QThread::sleep(1);
        qDebug() << "子线程号:" << QThread::currentThread();
        emit mysignal();  // 发送信号
    }
}

  主窗口类中

class myWidget : public QWidget
{
    myTHread *myT;   // 自定义线程对象
    QThread *thread; // 线程对象
signals:
    void startThread();  // 启动线程信号

private slots:
    // 启动线程
    void on_buttonStart_clicked();
    void dealsignal();   // 处理线程发送过来的信号
    // 停止线程
    void on_buttonStop_clicked();
}

  主窗口构造函数

// 分配空间 不能指定父对象  没有指定父对象最好最后 delete掉
    myT = new myTHread();

    // 创建子线程线程
    thread = new QThread(this);
    // 把自定义线程加入到子线程中
    myT->moveToThread(thread);

    qDebug() << "主线程号:"<<QThread::currentThread();
    // 线程任务结束信号  
    connect(myT,&myTHread::mysignal,this,&myWidget::dealsignal);
    
    connect(this,&myWidget::startThread,myT,&myTHread::mytimeout);
    // thread->isRunning();
    /* 线程处理函数内部不允许操作图形界面 弹出对话框也不行
     * connect()第五个参数的作用:
     * 连接方式:默认、队列、直接
     * 多线程的时候才会有意义:
     * 如果是多线程默认使用队列;
     * 如果是单线程,默认使用直接方式
     * 队列:槽函数所在的线程和信号接收者一样
     * 直接:槽函数所在线程和发送者一样;
     */

  

// 槽函数
void myWidget::dealsignal()
{
    static int i=0;
    i++;
    ui->lcdNumber->display(i);
}
// 按钮槽函数
void myWidget::on_buttonStart_clicked()
{
    myT->isStop = false;
    // 启动线程并没有启动线程处理函数
    thread->start();
    // 不能直接掉用线程处理函数
    // 否则 会导致子线程与主线程程在同一个线程

    // 只能通过信号---槽的形式调用startTread()
    emit startThread();
}
// 按钮槽函数
void myWidget::on_buttonStop_clicked()
{
    myT->isStop = true;  // 停止线程
    thread->quit();  // 线程退出
    thread->wait();  // 等待线程资源释放
}

 

posted @ 2020-08-10 23:16  笑不出花的旦旦  阅读(161)  评论(0)    收藏  举报