Qt线程的四种创建方式

 Qt中主线程负责界面显示和窗口控件的数据更新,子线程负责逻辑业务处理和数据计算,子线程不能对窗口有任何操作,子线程可通过信号槽来将数据传递给主线程。

1、子线程继承QThread

子线程继承QThread,然后重写run()函数来执行子线程

每一个子业务逻辑都可继承一个QThread来实现多线程

    m_thread = new MyThread;
    connect(m_thread, &MyThread::signalsThreadCalNum, this, [=](int num){
        ui->label->setNum(num);
    });
    connect(ui->pushButton_start, &QPushButton::clicked, m_thread, [=](){
        m_thread->start();
    });
    connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
        m_thread->Stop();
    });
class MyThread:public QThread
{
    Q_OBJECT
    //....
protected:
    void run();
}

void MyThread::run()
{
    int n = 0;
    while(n < 100000)
    {
        emit signalsThreadCalNum(n++);
        QThread::usleep(1);
    }
}

2、使用moveToThread

(1)任务类Task需要继承QObject,然后写一个执行任务的函数。

(2)创建一个QThread线程,然后调用moveToThread将对象移动到创建的子线程对象中

(3)启动子线程即可

    //创建子线程
    m_thread = new QThread;
    m_work = new MyWork;
    //将工作的类对象转移到创建的子线程对象中
    m_work->moveToThread(m_thread);

    //启动线程
    m_thread->start();
    //这种写法是错误的,界面卡顿,个人理解:接受者是this,相当于mainwiodnw调用
//    connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
//        m_work->Work();
//    });
    //ok
    connect(ui->pushButton_start, &QPushButton::clicked, m_work, [=](){
        m_work->Start();
    });

    connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
        m_work->Stop();
    });
    connect(m_work, &MyWork::signalsThreadCalNum, this, [=](int num){
        ui->label->setNum(num);
    });
class MyWork:public QObject
{
    //......
}

void MyWork::Work()
{
    int n = 0;
    while(n < 1000)
    {
        if(m_stop)
            break;
        emit signalsThreadCalNum(n++);
        QThread::usleep(1);
    }
}

 3、使用QtConcurrent

(1)pro中需要加上 QT += concurrent

(2)任务类中重写run()函数

    MyThread *mythread = new MyThread;
    connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
        QtConcurrent::run(mythread, &MyThread::Work);
    });
    connect(mythread, &MyThread::signalsThreadCalNum, this, [=](int num){
        ui->label->setNum(num);
    });
    connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
        mythread->Stop();
    });
void MyThread::Work()
{
    m_stop = false;
    int n = 0;
    while(n < 100000)
    {
        if(m_stop)
            break;
        emit signalsThreadCalNum(n++);
        QThread::usleep(1);
    }
}

4、使用线程池

使用QRunnable和QThreadPool

(1)任务类需要继承QRunnable,需要使用信号槽的话可多重继承QObject

(2)重写run函数

(3)使用QThreadPool::globalInstance()->start(QRunable *)来启动线程池

    // 线程池初始化,设置最大线程池数
    QThreadPool::globalInstance()->setMaxThreadCount(4);

    //创建任务
    MyThread *mythread = new MyThread;

    //start启动线程池
    connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
        QThreadPool::globalInstance()->start(mythread);
        mythread->Start();
    });
    connect(mythread, &MyThread::signalsThreadCalNum, this, [=](int num){
        ui->label->setNum(num);
    });
    connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
        mythread->Stop();
    });
/*
 * 线程池使用需要继承QRunnable
*/
class MyThread : public QObject, public QRunnable
{
    //.....
}

MyThread::MyThread(QObject *parent) : QObject(parent), QRunnable()
{
    setAutoDelete(true);
}

void MyThread::run()
{
    m_stop = false;
    int n = 0;
    while(n < 100000)
    {
        if(m_stop)
            break;
        emit signalsThreadCalNum(n++);
        QThread::usleep(1);
    }
}

5、线程池中可不采用多重继承QObject,可采用

QMetaObject::invokeMethod来实现

mainwindow.h中添加 



    Q_INVOKABLE void Show(int num);

 mainwindow.cpp



//mainwindow.cpp

    // 线程池初始化,设置最大线程池数
    QThreadPool::globalInstance()->setMaxThreadCount(4);

    //创建任务
    MyThread *mythread = new MyThread(this);

    //start启动线程池
    connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
        QThreadPool::globalInstance()->start(mythread);
        mythread->Start();
    });

    connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
        mythread->Stop();
    });

void MainWindow::Show(int num)
{
    ui->label->setNum(num);
}

 子线程中

void MyThread::run()
{
    m_stop = false;
    int n = 0;
    while(n < 100000)
    {
//        if(m_stop)
//            break;
        QMetaObject::invokeMethod(m_pObj, "Show", Q_ARG(int, n++));
        //emit signalsThreadCalNum(n++);
        QThread::usleep(1);
    }
}

 

你可能感兴趣的:(Qt)