QT QThread 多线程 用法二

版权声明: https://blog.csdn.net/xiezhongyuan07/article/details/86595818

        在上一篇文章中,我们介绍了QThread 的用法一,就是通过moveToThread将一个 继承于QObject的对象移到一个新的线程中执行(只能通过信号槽、事件进行调用才会在多线程中运行)详情请见:https://blog.csdn.net/xiezhongyuan07/article/details/86580080

上次我们介绍的那种方法,两个类都是继承于QObject的,那么还有种方法,就是继承于QThread的类,这也是另外一种方法,还上一种还有很多不一样的地方。

1.创建一个基于QObject的类Controller.(在此类中创建多线程的对象,并启动多线程)

2.创建一个基于QThread的类Worker(运行在单独的线程中)

3.在Worker类中,实现虚函数 void run();(所有run函数里的代码,终将在多线程里运行)

protected:
    void run();

4.在Controller类里,连接信号槽,然后通过start()启动线程

    m_worker = new Worker(this);
    connect(m_worker, &Worker::finished, this, &Controller::stopWork);
    m_worker->start();      //启动线程(调用run函数在多线程中运行)

这里有个在上篇文章里一样的问题:通过直接调用、信号槽调用、run()函数,这三种情况,都是在主线程执行还是在新建的线程里运行?

这点一定要弄清楚,要不然就是多线程使用的不正确,多线程使用起来,也没什么意义了。

老规矩,我们还是先来做个demo验证一下上面三种调用方式,哪种才会在新建的线程里运行。

Controller类:

Controller::Controller(QObject *parent)
    : QObject(parent)
    , m_worker(Q_NULLPTR)
{
    m_worker = new Worker(this);

    qDebug() << "main thread id = "<< QThread::currentThreadId();

    connect(this, &Controller::sigCall, m_worker, &Worker::signalCall);
    connect(m_worker, &Worker::finished, this, &Controller::stopWork);

    m_worker->start();      //启动线程(调用run函数在多线程中运行)
    m_worker->directCall(); //直接调用(在主线程中运行)

    emit sigCall();
}

Controller::~Controller()
{
    stopWork();
}

void Controller::stopWork()
{
    qDebug() << "stop work thread id=" << QThread::currentThreadId();
    if (m_worker != Q_NULLPTR) {
        m_worker->quit();
        m_worker->wait();
    }
}

Worker类:

Worker::Worker(QObject *parent)
    :QThread(parent)
{
}

Worker::~Worker()
{
}

// 调用thread->start() ,后会自动执行run()函数    
void Worker::run()
{
    qDebug() << "run worker thread id = " << QThread::currentThreadId();
}

// 当做类的普通对象进行调用
void Worker::directCall()
{
    qDebug() << "direct call worker thread id = " << QThread::currentThreadId();
}

// 通过信号槽进行调用
void Worker::signalCall()
{
    qDebug() << "signal call worker thread id = " << QThread::currentThreadId();
}

那么这样执行的结果是什么呢?

Starting E:\demo\build-threadDemo1-Desktop_Qt_5_7_0_MSVC2013_32bit-Debug\debug\threadDemo1.exe...
main thread id =  0x46a0                    //主线程id
direct call worker thread id =  0x46a0      //直接调用 代码运行的线程id
signal call worker thread id =  0x46a0      //信号槽调用 代码运行的线程id
run worker thread id =  0x2b64              //在run函数里代码运行的线程id
stop work thread id= 0x46a0                 //

那么结论就出来了,很明显,

通过直接调用, 是运行在主线程里(与moveToThread结果一样)相当于普通的函数调用;

通过信号槽调用, 也是运行在主线程里(与moveToThread的结果不一样);

run()函数里的代码是新的线程里;

所以通过继承于QThread这种方式使用多线程,我们就不能使用信号槽进行调用了,只能是重写void run()函数,所有需要计算或者耗时的代码,都在run函数里进行执行,才是正确的使用方法。

猜你喜欢

转载自blog.csdn.net/xiezhongyuan07/article/details/86595818