Qt之QThread

实现线程的两种方法:

(1) 派生QThread并重写run()函数;

(2) 使用 QObject::moveToThread(QThread); (推荐 )

1. 常用接口 

槽函数:

​​作用: 开启线程,通过调用run函数开始线程执行;操作系统根据优先级参数调度线程;若该线程已经运行了,
则该函数什么也不做;
void QThread::start(QThread::Priority priority = InheritPriority);

enum Priority {
    IdlePriority,//只有在没有其他线程运行时才调度。

    LowestPriority,//调度频率低于LowPriority。
    LowPriority,  //调度频率低于NormalPriority。
    NormalPriority,//操作系统的默认优先级。
    HighPriority, //调度比NormalPriority更频繁。
    HighestPriority,//调度比HighPriority更频繁

    TimeCriticalPriority,//尽可能的被调度

    InheritPriority //使用与创建线程相同的优先级。这是默认值。
};

作用:终止线程的执行;该线程可能立即终止,也可能不会;取决于操作系统调度策略;
所以terminate后应该使用 wait函数;
void QThread::terminate();

作用:告诉线程事件循环退出,返回0; 等同于exit(0); 若没有事件循环,则什么都不做;
void QThread::quit();

 信号:

该信号从关联的线程 在run()函数运行前发出;
void started();

该信号从关联的线程 在完成执行前发出;当信号被发出时,事件循环已经停止运行了;
void finished();

线程被中断时候发出
void terminated();//qt5可能取消;

公共函数: 

设置调度优先级
void setPriority(Priority priority);

获取调度优先级
Priority priority() const;
设置栈大小,stackSize>0设置才有效;注意:线程运行时不可以改变栈大小;
void QThread::setStackSize(uint stackSize);

获取栈大小
uint QThread::stackSize() const
如果线程结束,返回true;否则返回false。
bool isFinished() const;

如果线程正在运行,返回true;否则返回false。
bool isRunning() const;

静态成员:

线程延时函数:强制该线程延时一段时间;
static void sleep(unsigned long);
static void msleep(unsigned long);
static void usleep(unsigned long);

//获取该线程句柄,为void *;  
static Qt::HANDLE currentThreadId();

//返回管理该线程对象的指针
static QThread *currentThread();

保护成员函数:

进入事件循环并且等待,直到exit(0)被调用; 
这个函数应该在run()中调用。需要调用此函数来启动事件处理。
int QThread::exec();

线程的起始点。在调用start()之后,新创建的线程调用这个函数。默认实现只调用exec()。
void QThread::run();

2. 派生QThread并重写run()函数

(a) 子类化QThread,重写run,run中使用while循环,设置退出标志;

class MyThread : public QThread
{
    Q_OBJECT

public:
    MyThread(){isRuning = true;}

    //改变线程运行状态
    void ChangeThreadRunStatus(bool status)
    {
        isRuning = status;
    }

 protected:
    void run()
    {
        while(isRuning) 
        {
            qDebug() << "thread is running..." << endl;

            sleep(1);
        }
    }

private:
    bool isRuning ;
};

//测试头文件
class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void closeEvent(QCloseEvent *e);

private:
    Ui::Widget *ui;
    MyThread   *mythread;
};

//测试cpp
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    mythread = new MyThread();
    connect(mythread, SIGNAL(finished()), mythread, SLOT(deleteLater()));
    mythread->start();
}

Widget::~Widget()
{
    //从Qt4.8开始,通过将finished()信号连接到QObject::deleteLater(),可以释放刚刚结束的线程中的对象。尽可能的使用deleteLater方法释放内存;
    #if 0
    mythread->exit(0);
    //等待线程完全退出后在析构
    //不等待会出现 QThread: Destroyed while thread is still running
    //线程的run中有一个sleep,不等待可能run没退出就delete掉该线程;
    mythread->wait();
    delete mythread;
    #endif

    delete ui;
}

void Widget::closeEvent(QCloseEvent *e)
{
    qDebug() << "closeEvent" << endl;
    mythread->ChangeThreadRunStatus(false);//关闭窗口时停止线程;
}

(b) 子类化QThread,重写run()函数,在run中调用exec事件循环;

在其中使用信号和槽, 由于槽函数并没有运行子线程中(参考);故用moveToThread方法;

 

3. 使用 QObject::moveToThread(QThread)方法

参考: 【QT】子类化QObject+moveToThread实现多线程 | 程序员灯塔

官方文档:https://doc.qt.io/qt-5/qthread.html#run

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值