QT QThread 多线程 用法一

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

QThread 用法探究一:

QT使用moveThread开启多线程:

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

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

3.在Worker类中,创建一个槽函数doWorker(); 用于运行多线程里面的代码,所有耗时的代码全部在这个槽函数里面运行。

4.在Controller里面将Worker 的实例调用moveToThread(QThread *thread),并连接信号槽。并start()启动线程。(为什么使用信号槽调用呢?为什么不可以直接m_worker->signalCall()呢?

    m_worker = new Worker();

    m_worker->moveToThread(&m_thread);

    connect(&m_thread, &QThread::started, m_worker, &Worker::signalCall);//多线程开始工作
    connect(&m_thread, &QThread::finished, m_worker, &Worker::deleteLater);//
    connect(m_worker, &Worker::finished, this, &Controller::stopWork);//线程类结束后,通知删除


    m_thread.start(); //线程开始

5.在Controller的析构函数里调用:

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

void Controller::stopWork()
{
    if (m_worker != Q_NULLPTR) {
        m_worker->deleteLater();
        m_worker = Q_NULLPTR;
    }

    if (m_thread.isRunning()) {
        m_thread.quit();
        m_thread.wait();
    }
}

下面我们来验证一下,为什么不能直接调用函数,而需要通过信号槽进行调用。

Controller:

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

    m_worker->moveToThread(&m_thread);

    connect(&m_thread, &QThread::started, m_worker, &Worker::signalCall);
    connect(&m_thread, &QThread::finished, m_worker, &Worker::deleteLater);
    connect(m_worker, &Worker::finished, this, &Controller::stopWork);

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

    m_worker->directCall();//验证为什么不能直接调用函数,而是通过信号槽进行调用

    m_thread.start();
}

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

void Controller::stopWork()
{
    if (m_worker != Q_NULLPTR) {
        m_worker->deleteLater();
        m_worker = Q_NULLPTR;
    }

    if (m_thread.isRunning()) {
        m_thread.quit();
        m_thread.wait();
    }
}

Worker类:

Worker::Worker(QObject *parent)
{

}

Worker::~Worker()
{

}

void Worker::directCall()
{
    qDebug() << "direct call thread id = " << QThread::currentThreadId();
}

void Worker::signalCall()
{
    qDebug() << "signal slot call  thread id = " << QThread::currentThreadId();
}

我们在Worker类中有两个函数,directCall与signalCall两个函数,分别是对Worker类的实例直接调用通过信号槽调用,看看有什么不同。

result:
main controller thread id =  0x426c        //主线程id
direct call thread id =  0x426c            //直接调用,发生在的线程
signal slot call  thread id =  0x3814      //通过信号槽调用,发生的线程

通过结果,我们可以看到:

主线程的线程id为0x426c

通过直接调用,函数执行在线程0x426c

通过信号槽调用,函数执行再线程0x3814

可以看到,如果通过直接调用的话, 还是会在主线程中执行函数,与普通的函数调用相同。

如果通过信号槽调用,则是在多线程中执行。这才是达到我们的目的。

结论:

通过moveToThread运用新线程中,需要通过信号槽、事件等才能在多线程中执行。如果通过直接调用的话,则还是在主线程中执行。

猜你喜欢

转载自blog.csdn.net/xiezhongyuan07/article/details/86580080
今日推荐