【Qt】多线程QRunnable

用法

要使用QRunnable创建线程,步骤如下:

  • 继承QRunnable。和QThread使用一样,首先需要将你的线程类继承于QRunnable。
  • 重写run函数。还是和QThread一样,需要重写run函数,run是一个纯虚函数,必须重写。
  • 使用QThreadPool启动线程。

和QThread的区别

与外界通信方式不同。由于QThread是继承于QObject的,所以可以在线程类中使用信号槽,但QRunnable没有继承于QObject,所以不能使用信号与槽。

启动线程方式不同。QThread线程可以直接调用start()函数启动,而QRunnable线程需要借助QThreadPool进行启动。

资源管理不同。QThread线程对象需要手动去管理删除和释放,而QRunnable则会在QThreadPool调用完成后自动释放。

#ifndef CUSRUNNABLE_H
#define CUSRUNNABLE_H

#include 

class CusRunnable : public QRunnable
{
public:
    CusRunnable();
    ~CusRunnable();
    void run() override;
};

#endif // CUSRUNNABLE_H
#include "cusrunnable.h"
#include 
#include 
CusRunnable::CusRunnable()
{

}

CusRunnable::~CusRunnable()
{
   qDebug()<<"~CusRunnable";
}

void CusRunnable::run()
{
    for(int i=0;i<10;i++)
    {
        qDebug()<<"doWork %d"<
    CusRunnable* run=new CusRunnable();
    qDebug()<<"main thread_id="<start(run);
main thread_id= 0x7004
doWork %d 0  thread_id 0x6228
doWork %d 1  thread_id 0x6228
doWork %d 2  thread_id 0x6228
doWork %d 3  thread_id 0x6228
doWork %d 4  thread_id 0x6228
doWork %d 5  thread_id 0x6228
doWork %d 6  thread_id 0x6228
doWork %d 7  thread_id 0x6228
doWork %d 8  thread_id 0x6228
doWork %d 9  thread_id 0x6228
~CusRunnable

启动线程方式

上面说到启动QRunnable线程需要QThreadPool,而调用方式有两种:全局线程池和非全局线程池。

全局线程池如上面示例中。非全局线程池其实就是自己实例化一个QThreadPool对象,我们可以控制线程最大数量等。

    CusRunnable* run=new CusRunnable();
    qDebug()<<"main thread_id="<

与外界通信

因为QRunnable没有继承于QObject,所以没法使用信号与槽。QRunnable与外界通信有两种方式:

  • 使用多继承。让自定义的线程类同时继承于QRunnable和QObject,这样就可以使用信号与槽了,但是项目中尽量少用多继承。
  • 使用QMetaObject::invokeMethod

QMetaObject::invokeMethod

函数定义如下:

[static] bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument( Q_NULLPTR ), QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument())

该函数就是尝试调用obj的member函数,可以是信号、槽或者Q_INVOKABLE声明的函数(能够被Qt元对象系统唤起),如果调用成功,返回true,失败返回false。
QMetaObject::invokeMethod可以是异步调用,也可以是同步调用。这取决与它的连接方式Qt::ConnectionType type。如果type为Qt::DirectConnection,则为同步调用,若为Qt::QueuedConnection,则为异步调用。

首先,我们在使用CusRunnable类的类中定义如下函数:

Q_INVOKABLE  void onResultReady(const QString result);

void SIHToolBar::onResultReady(const QString result)
{
    qDebug()<<"onResultReady result="<CusRunnable(QObject* obj);

最后,我们在run函数中调用这个对象的函数。

void CusRunnable::run()
{
    for(int i=0;i<10;i++)
    {
        qDebug()<<"doWork %d"<

你可能感兴趣的:(qt,QRunnable)