• Qt QThread 线程创建,线程同步,线程通信 实例


    1.  继承QThread, 实现run()方法, 即可创建线程。

    2. 实例1 代码

    myThread.h

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    
    #include <QThread>
    
    class myThread : public QThread   //myThread 线程类
    {
        Q_OBJECT
    
    public:
        myThread();
        void setMessage(const QString &message);
        void stop();
    protected:
        void run();   //复写run()方法,里面是线程 的 主体代码
    private:
        QString messageStr;
        volatile bool stopped;
    };
    
    #endif // MYTHREAD_H
    

    myThread.cpp

    #include "myThread.h"
    #include <QDebug>
    
    myThread::myThread()
    {
        stopped = false;
    }
    
    void myThread::run()  //实现run()方法, 隔1秒输出messageStr
    {
        while(!stopped)
        {
            qDebug() << messageStr << endl;
            sleep(1);
        }
        stopped = false;
    }
    
    void myThread::stop()
    {
        stopped = true;
    }
    
    void myThread::setMessage(const QString &message)
    {
        messageStr = message;
    }

    dialog.h

    #ifndef DIALOG_H
    #define DIALOG_H
    
    #include <QDialog>
    #include <QtGui>
    #include "myThread.h"
    
    class Dialog : public QDialog
    {
        Q_OBJECT
        
    public:
        Dialog(QWidget *parent = 0);
        ~Dialog();
    
    protected:
        void closeEvent(QCloseEvent *event);
    
    private slots:
        void startOrStopThreadA();
        void startOrStopThreadB();
    
    private:
        myThread threadA;   //用线程类 实例化 线程对象
        myThread threadB;
        QPushButton *threadAButton;
        QPushButton *threadBButton;
        QPushButton *quitButton;
    };
    
    #endif // DIALOG_H
    

    dialog.cpp

    #include "dialog.h"
    
    Dialog::Dialog(QWidget *parent)
        : QDialog(parent)
    {    
        threadA.setMessage("A");
        threadB.setMessage("B");
    
        threadAButton = new QPushButton(tr("Start A"));
        threadBButton = new QPushButton(tr("Start B"));
        quitButton = new QPushButton(tr("Quit"));
        quitButton->setDefault(true);
        connect(threadAButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadA()));
        connect(threadBButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadB()));
        connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
    
        QHBoxLayout *hLayout = new QHBoxLayout;
        hLayout->addWidget(threadAButton);
        hLayout->addWidget(threadBButton);
        hLayout->addWidget(quitButton);
        setLayout(hLayout);
    }
    
    Dialog::~Dialog()
    {    
    }
    
    void Dialog::startOrStopThreadA()
    {
        if( threadA.isRunning() )
        {
            threadA.stop();   //结束线程
            threadAButton->setText(tr("Start A"));
        }
        else
        {
            threadA.start();   //thread.start()开始线程
            threadAButton->setText(tr("Stop A"));
        }
    }
    
    void Dialog::startOrStopThreadB()
    {
        if( threadB.isRunning() )
        {
            threadB.stop();
            threadBButton->setText(tr("Start B"));
        }
        else
        {
            threadB.start();
            threadBButton->setText(tr("Stop B"));
        }
    }
    
    void Dialog::closeEvent(QCloseEvent *event)  //当用户点击quit按键  或 这退出UI的时候,回调closeEvent函数
    {
        threadA.stop();
        threadB.stop();
        threadA.wait();
        threadB.wait();
        event->accept();
        //qDebug("--log--");
    }
    
    


    3. 线程同步

    QT线程同步的类有: QMutex, QReadWriteLock, QSemaphore, QWaitcondition.

    QMutext互斥锁: 可以锁住一段代码,同一时间只能有一个线程访问。

    或者用简化锁QMutexLocked类, 构造函数输入QMutex并将其锁住, 析构函数将其解锁。

    QReadWriteLock类, 允许多个线程读共享资源,但是只允许一个线程写共享资源。


    QSemaphore 信号量 互斥量, 解决 生产者--消费者 问题



     

    4. 利用信号槽, 主线程和子线程通信,互相发送消息。

    子线程向主线程发送 每隔一秒向主线程发送累加数字, 主线程按键信息发送到子线程。。

    Thread.h

    #ifndef THREAD_H
    #define THREAD_H
    #include <QThread>
    
    class Thread : public QThread
    {
        Q_OBJECT
    private:
        int number;
    protected:
        void run();
    public:
        Thread(QObject *parent=0);
        ~Thread();
    signals:
        void UpdateSignal(int num);
    public slots:
        void ResetSlot();
    };
    
    #endif // THREAD_H
    

    Thread.cpp

    #include "Thread.h"
    
    Thread::Thread(QObject *parent)
    {
        number = 0;
    }
    
    Thread::~Thread()
    {
    }
    
    void Thread::run()
    {
        while(1)
        {
            emit UpdateSignal(number);  //发送更新信号给主线程,附带参数number
            number++;
            sleep(1);
        }
    }
    
    void Thread::ResetSlot()
    {
        number = 0;
        emit UpdateSignal(number);  //发送重置number信号
    }
    

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QtGui>
    #include "Thread.h"
    
    class Widget : public QWidget
    {
        Q_OBJECT
        
    public:
        Widget(QWidget *parent = 0);
        ~Widget();
    
    private:
        QLabel *label;
        QPushButton *startButton;
        QPushButton *stopButton;
        QPushButton *resetButton;
        Thread *myThread;
        int number;
    
    signals:
        void ResetSignal();
    
    public slots:
        void clearSlot();
        void startSlot();
        void stopSlot();
        void updateSlot(int num);
    
    };
    
    #endif // WIDGET_H
    

    widget.cpp

    #include "widget.h"
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
        startButton = new QPushButton("start");
        stopButton = new QPushButton("stop");
        resetButton = new QPushButton("reset");
        label = new QLabel("empty");
    
        myThread = new Thread();
    
        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(label);
        layout->addWidget(startButton);
        layout->addWidget(stopButton);
        layout->addWidget(resetButton);
        setLayout(layout);
    
        connect(stopButton, SIGNAL(clicked()), this, SLOT(stopSlot()));
        connect(startButton, SIGNAL(clicked()), this, SLOT(startSlot()));
        connect(resetButton, SIGNAL(clicked()), this, SLOT(clearSlot()));
        connect(myThread, SIGNAL(UpdateSignal(int)), this, SLOT(updateSlot(int)));   //子线程发信号给主线程,更新number
        connect(this, SIGNAL(ResetSignal()), myThread, SLOT(ResetSlot()));   //主线程发信号给子线程,重置number信号
    
        resize(200, 200);
    
    }
    
    Widget::~Widget()
    {
        
    }
    
    void Widget::startSlot()
    {
        myThread->start();
    }
    
    void Widget::stopSlot()
    {
        myThread->terminate();
    }
    
    void Widget::updateSlot(int num)
    {
        label->setText(QString::number(num));
    }
    
    void Widget::clearSlot()
    {
        emit ResetSignal();     //主线程发送重置信号 给 子线程
    }
    



     

  • 相关阅读:
    javascript keycode大全
    在WEB环境下打印报表的crystal的解决方案
    Trim()
    C#应用结构体变量
    锚点定位
    C# 按地址传值
    [GIIS]JS 图片 Preview
    c# 模拟网站登陆
    此数据库没有有效所有者,因此无法安装数据库关系图支持对象" 解决方法
    风讯.NET与NETCMS的选择—开源.NET内容管理系统
  • 原文地址:https://www.cnblogs.com/xj626852095/p/3648131.html
Copyright © 2020-2023  润新知